From nobody Tue May 06 17:15:08 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ZsQ4s1zGmz5v7DZ; Tue, 06 May 2025 17:15:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZsQ4r5GwTz3gg4; Tue, 06 May 2025 17:15:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1746551708; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=asajJLh3rbuRDfOVS84a+d1vu1Bt3cc8ZoeskeVbRnM=; b=kjb4yZh0eQp78lBZI7b0UXyP84RxHu2aK9mt079QyHJB9LEEBom8aY8Dp955QCwJ+CBBUC BF2njze5g32HTw70I2FBqlAmdj5sAnGNlEFCeaSdFReo6dZclFkE6/4HBoAP1Idh5A04bX j78nD9+U5XVOOkEK6csDClN6jOe3+vKci5PJ0U0t74nEyRUkeiwb3fJJ4zOCK1ZFFyuCH9 c2Hv3IgkEP/I15YCHynIHv4hyJcs/d+9NZQXFBv/AtoTRXPE7hspX95EZF/8MZM21TXBhO cTrwmKLCN1gQhjuuDAZzvh/YqGRTQsiSrXcocXgfGnsMX16LbJ8DJDo6w+umUQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1746551708; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=asajJLh3rbuRDfOVS84a+d1vu1Bt3cc8ZoeskeVbRnM=; b=MonjAzY2VZN19XwFJ8zLxcKDi+euUM7/t8wA1Yi70ZeI0BFHxBIFdVOIInvdK8Oxc5PjYW O7HapwiyL4cBNZBo2pvCSGc8t8xj0A+O5wE98XXCHQrwQtp3N69YJSpOkDnBWSNWVToGJ0 WmDlL03sVqY8eGqgvbVoU9u+TdrIssUC7IMqH3irs0o011YDVcp+DsmcSUJeoXh1jzK4ea mJ3tmryrQ2J2uIyFmneauC84pB+KFJBTtC9KdYxA1Ui+qYqHVp8PIiX9/7MBtIjX1yfHNH mGcVxIUDHOD/HyV0BD+8iRVORvbYN484HUtyZBz6YC6dYAH9poPDlarEmtq8bg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1746551708; a=rsa-sha256; cv=none; b=ImgjrK6yXS7DowSzuXx9yLdaw/M5oSk0/Is2Z1AT+nfuirNvXKPvPLi1+0sN1umn2qnq4m KeXX7FiQrLkBOdV7/7WPrbkxvOtW/3DS39YPjGkq2YVIYmWMs37/KWyTFx5vMQMlcaUC/3 peIRxZ5psNQioZGLMX4XNffr4VXO10asg34NxLe6h/OemIPc23NdaekuvkX4MKyY//Jt7K /K8DVFnsseXQQHWWjpkCTzuhToXxRJwN+UwuLALQ0IFX8HVtyfMCcHyu4u9a/xzjUultns a4vYcYyb7nadaCtT00uxJNP+QBpLpQcQrLAisvrRgsX+QFwVLdatZUqPa3itpw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ZsQ4r4dkPz17nr; Tue, 06 May 2025 17:15:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 546HF8pZ089401; Tue, 6 May 2025 17:15:08 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 546HF8WB089398; Tue, 6 May 2025 17:15:08 GMT (envelope-from git) Date: Tue, 6 May 2025 17:15:08 GMT Message-Id: <202505061715.546HF8WB089398@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 78aaab9f1cf3 - main - rtld: add support for -z initfirst List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 78aaab9f1cf359f3b7325e4369653f6b50593393 Auto-Submitted: auto-generated The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=78aaab9f1cf359f3b7325e4369653f6b50593393 commit 78aaab9f1cf359f3b7325e4369653f6b50593393 Author: Konstantin Belousov AuthorDate: 2025-05-03 08:14:25 +0000 Commit: Konstantin Belousov CommitDate: 2025-05-06 17:14:56 +0000 rtld: add support for -z initfirst Internally, initfirst objects and their needed objects are put on the dedicated initlist, which is prepended to the current regular initlist at the last moment. This results in the move of the needed objects into the beginning of the initlist, which is required for the proper initialization of the dependencies. It seems that glibc moves only the initfirst object, which makes its constructors depend on not yet initialized dsos. Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D50132 --- libexec/rtld-elf/rtld.c | 127 ++++++++++++++++++++++++++++++++++++------------ libexec/rtld-elf/rtld.h | 1 + 2 files changed, 97 insertions(+), 31 deletions(-) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 0575ce19d476..12aee444fccf 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -112,8 +112,11 @@ static void init_dag(Obj_Entry *); static void init_marker(Obj_Entry *); static void init_pagesizes(Elf_Auxinfo **aux_info); static void init_rtld(caddr_t, Elf_Auxinfo **); -static void initlist_add_neededs(Needed_Entry *, Objlist *); -static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *); +static void initlist_add_neededs(Needed_Entry *, Objlist *, Objlist *); +static void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *, + Objlist *); +static void initlist_for_loaded_obj(Obj_Entry *obj, Obj_Entry *tail, + Objlist *list); static int initlist_objects_ifunc(Objlist *, bool, int, RtldLockState *); static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); @@ -952,7 +955,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) /* Make a list of init functions to call. */ objlist_init(&initlist); - initlist_add_objects(globallist_curr(TAILQ_FIRST(&obj_list)), + initlist_for_loaded_obj(globallist_curr(TAILQ_FIRST(&obj_list)), preload_tail, &initlist); r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ @@ -1564,6 +1567,8 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, obj->z_nodeflib = true; if (dynp->d_un.d_val & DF_1_PIE) obj->z_pie = true; + if (dynp->d_un.d_val & DF_1_INITFIRST) + obj->z_initfirst = true; break; default: @@ -2543,15 +2548,15 @@ init_pagesizes(Elf_Auxinfo **aux_info) * when this function is called. */ static void -initlist_add_neededs(Needed_Entry *needed, Objlist *list) +initlist_add_neededs(Needed_Entry *needed, Objlist *list, Objlist *iflist) { /* Recursively process the successor needed objects. */ if (needed->next != NULL) - initlist_add_neededs(needed->next, list); + initlist_add_neededs(needed->next, list, iflist); /* Process the current needed object. */ if (needed->obj != NULL) - initlist_add_objects(needed->obj, needed->obj, list); + initlist_add_objects(needed->obj, needed->obj, list, iflist); } /* @@ -2564,36 +2569,96 @@ initlist_add_neededs(Needed_Entry *needed, Objlist *list) * held when this function is called. */ static void -initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list) +initlist_for_loaded_obj(Obj_Entry *obj, Obj_Entry *tail, Objlist *list) { - Obj_Entry *nobj; + Objlist iflist; /* initfirst objs and their needed */ + Objlist_Entry *tmp; - if (obj->init_scanned || obj->init_done) - return; - obj->init_scanned = true; + objlist_init(&iflist); + initlist_add_objects(obj, tail, list, &iflist); - /* Recursively process the successor objects. */ - nobj = globallist_next(obj); - if (nobj != NULL && obj != tail) - initlist_add_objects(nobj, tail, list); + STAILQ_FOREACH(tmp, &iflist, link) { + Obj_Entry *tobj = tmp->obj; - /* Recursively process the needed objects. */ - if (obj->needed != NULL) - initlist_add_neededs(obj->needed, list); - if (obj->needed_filtees != NULL) - initlist_add_neededs(obj->needed_filtees, list); - if (obj->needed_aux_filtees != NULL) - initlist_add_neededs(obj->needed_aux_filtees, list); + if ((tobj->fini != (Elf_Addr)NULL || + tobj->fini_array != (Elf_Addr)NULL) && + !tobj->on_fini_list) { + objlist_push_tail(&list_fini, tobj); + tobj->on_fini_list = true; + } + } - /* Add the object to the init list. */ - objlist_push_tail(list, obj); + /* + * This might result in the same object appearing more + * than once on the init list. objlist_call_init() + * uses obj->init_scanned to avoid dup calls. + */ + STAILQ_REVERSE(&iflist, Struct_Objlist_Entry, link); + STAILQ_FOREACH(tmp, &iflist, link) + objlist_push_head(list, tmp->obj); - /* Add the object to the global fini list in the reverse order. */ - if ((obj->fini != (Elf_Addr)NULL || - obj->fini_array != (Elf_Addr)NULL) && - !obj->on_fini_list) { - objlist_push_head(&list_fini, obj); - obj->on_fini_list = true; + objlist_clear(&iflist); +} + +static void +initlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list, + Objlist *iflist) +{ + Obj_Entry *nobj; + + if (obj->init_done) + return; + + if (obj->z_initfirst || list == NULL) { + /* + * Ignore obj->init_scanned. The object might indeed + * already be on the init list, but due to being + * needed by an initfirst object, we must put it at + * the head of the init list. obj->init_done protects + * against double-initialization. + */ + if (obj->needed != NULL) + initlist_add_neededs(obj->needed, NULL, iflist); + if (obj->needed_filtees != NULL) + initlist_add_neededs(obj->needed_filtees, NULL, + iflist); + if (obj->needed_aux_filtees != NULL) + initlist_add_neededs(obj->needed_aux_filtees, + NULL, iflist); + objlist_push_tail(iflist, obj); + } else { + if (obj->init_scanned) + return; + obj->init_scanned = true; + + /* Recursively process the successor objects. */ + nobj = globallist_next(obj); + if (nobj != NULL && obj != tail) + initlist_add_objects(nobj, tail, list, iflist); + + /* Recursively process the needed objects. */ + if (obj->needed != NULL) + initlist_add_neededs(obj->needed, list, iflist); + if (obj->needed_filtees != NULL) + initlist_add_neededs(obj->needed_filtees, list, + iflist); + if (obj->needed_aux_filtees != NULL) + initlist_add_neededs(obj->needed_aux_filtees, list, + iflist); + + /* Add the object to the init list. */ + objlist_push_tail(list, obj); + + /* + * Add the object to the global fini list in the + * reverse order. + */ + if ((obj->fini != (Elf_Addr)NULL || + obj->fini_array != (Elf_Addr)NULL) && + !obj->on_fini_list) { + objlist_push_head(&list_fini, obj); + obj->on_fini_list = true; + } } } @@ -3863,7 +3928,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, */ } else { /* Make list of init functions to call. */ - initlist_add_objects(obj, obj, &initlist); + initlist_for_loaded_obj(obj, obj, &initlist); } /* * Process all no_delete or global objects here, given diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 383b8db2114c..d1ea00b96627 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -246,6 +246,7 @@ typedef struct Struct_Obj_Entry { bool z_nodeflib : 1; /* Don't search default library path */ bool z_global : 1; /* Make the object global */ bool z_pie : 1; /* Object proclaimed itself PIE executable */ + bool z_initfirst : 1; /* Proceed initializers before other objects */ bool static_tls : 1; /* Needs static TLS allocation */ bool static_tls_copied : 1; /* Needs static TLS copying */ bool ref_nodel : 1; /* Refcount increased to prevent dlclose */