1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-24 07:40:52 +00:00

rtld: add LD_NO_DL_ITERATE_PHDR_AFTER_FORK env var

which makes threaded fork ignore the phdr rtld lock, in particular
allowing the dl_iterate_phdr() to block in callback.  The cost is that
the image started in this mode cannot use dl_iterate_phdr() after fork.

PR:	280318
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2024-07-17 07:05:33 +03:00
parent 47315d6d35
commit 860c4d94ac
4 changed files with 16 additions and 3 deletions

View File

@ -26,7 +26,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd April 28, 2024
.Dd July 24, 2025
.Dt RTLD 1
.Os
.Sh NAME
@ -329,6 +329,14 @@ The static TLS extra space is used when loading objects compiled for
initial-exec TLS code model with
.Xr dlopen 3 .
The minimum value that can be specified is \'128\'.
.It Ev LD_NO_DL_ITERATE_PHDR_AFTER_FORK
Allow
.Xr dl_iterate_phdr 3
to block in callback, without causing deadlock with the
.Xr fork 2 .
The drawback is that the image started in this mode cannot use
.Xr dl_iterate_phdr 3
after fork.
.El
.Sh DIRECT EXECUTION MODE
.Nm

View File

@ -375,6 +375,7 @@ static struct ld_env_var_desc ld_env_vars[] = {
LD_ENV_DESC(TRACE_LOADED_OBJECTS_ALL, false),
LD_ENV_DESC(SHOW_AUXV, false),
LD_ENV_DESC(STATIC_TLS_EXTRA, false),
LD_ENV_DESC(NO_DL_ITERATE_PHDR_AFTER_FORK, false),
};
const char *

View File

@ -376,6 +376,7 @@ enum {
LD_TRACE_LOADED_OBJECTS_ALL,
LD_SHOW_AUXV,
LD_STATIC_TLS_EXTRA,
LD_NO_DL_ITERATE_PHDR_AFTER_FORK,
};
void _rtld_error(const char *, ...) __printflike(1, 2) __exported;

View File

@ -463,6 +463,7 @@ _rtld_atfork_pre(int *locks)
if (locks == NULL)
return;
bzero(ls, sizeof(ls));
/*
* Warning: this did not worked well with the rtld compat
@ -472,7 +473,8 @@ _rtld_atfork_pre(int *locks)
* _rtld_atfork_pre() must provide the working implementation
* of the locks anyway, and libthr locks are fine.
*/
wlock_acquire(rtld_phdr_lock, &ls[0]);
if (ld_get_env_var(LD_NO_DL_ITERATE_PHDR_AFTER_FORK) == NULL)
wlock_acquire(rtld_phdr_lock, &ls[0]);
wlock_acquire(rtld_bind_lock, &ls[1]);
/* XXXKIB: I am really sorry for this. */
@ -492,5 +494,6 @@ _rtld_atfork_post(int *locks)
ls[0].lockstate = locks[2];
ls[1].lockstate = locks[0];
lock_release(rtld_bind_lock, &ls[1]);
lock_release(rtld_phdr_lock, &ls[0]);
if (ld_get_env_var(LD_NO_DL_ITERATE_PHDR_AFTER_FORK) == NULL)
lock_release(rtld_phdr_lock, &ls[0]);
}