From nobody Thu Apr 9 08:25:47 2026 X-Original-To: dev-commits-src-branches@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 4frtL41D2fz6YkF3 for ; Thu, 09 Apr 2026 08:25:48 +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 "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4frtL33BGZz3CSt for ; Thu, 09 Apr 2026 08:25:47 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775723147; 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=JqOa0Ugiugzb0HqE+0HHRayardcSlPFSt5OjgragBF4=; b=utXmCflKAag0BYGhfrJbqkwyJNpZtMyvsdLaVazz4fcwX5R9SftCx7p/RSXucvdHtb6wPN sFRYnBVHju8fyktcTB5TLrmUaqQB6hkM4FE7BKb/heC5SfzbMVW1W9tWs0e0+GTyCr0PBe QIDGye6t8RXGR8lMw+gQjoe2ulB+9WBRd4XwcoMZbBg5x8PdNLEKQ3uq696MpmiNUrtAUT jEzEd2UsPVzRw28A18qPG04ndCTMYAw7zGMD5zQpCn+QSU50tXlgGF1tlZjSv8Ff4dZ+CN PGji8qxUeYkC9R/ufofIBoWkuUe7IGO/FUPGERuNvlh85L++7aLEQpKPX09F4w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1775723147; a=rsa-sha256; cv=none; b=j80+8ZvY3IiVROGeKfT34vxX+QbZqY3GTgJHp9nRTJMwpGzoEcumlmw3P+wg7ITEXrCtVH XTs3nOPhmo6J6CZsOUyD+Mx/lhQzFILwc6IzkC9dwDOjxZH675bsjH8dr8QihSafXz0mEH ccFIuCcQp8LLf0vn9He6CsMbdWpVB7/yxf18sdYc4MqgqZpaeWn/d4cAjLDaX3wR3OBGOa SjNr/W4ywSL72HP++hofo94rsQNem19+rTrHtMxGHzb3h/wNyL4pJ61CDZ70uCvH1EonSj v8BVIynn31azHjzNz8YtJ+28m8ZQ6sDfbh7ifskyc3BTcu1q5s69XjyjPWcXsw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775723147; 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=JqOa0Ugiugzb0HqE+0HHRayardcSlPFSt5OjgragBF4=; b=v2nsKKtzN2FC4KaqATzdHjXz99PEJjhbz0i9mk+iMZZrfpWL9Cm/jEClzyTs/czb1IwdTD QPFqFlixGPe3JO9jxNsI1C1AmeF6E13aXzX51FSHwQmNkuZnN2w3NwrjkGcwCsOPhTnYs0 p8dBcE/I/M8CG3hWaQmZhzB1tgN5UZvfF2QZPXMWsljFGe6fTEaXBy4RM5cuVopxCPmJha cDu+vigxGjEltvKAapwq8kdir/J29K3rlEmgdBzrjK8YwkjgOVBjSddUZCg4rnNcjYHWnv 1LpNnLOjC9OBC/eXhf6b10DJCyUUSCpzxs5Ijn6EAZeoaBRZrGPCO3ULVfLBlQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4frtL32Vfgz14dJ for ; Thu, 09 Apr 2026 08:25:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3fa95 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 09 Apr 2026 08:25:47 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: 8fb16a5c7f81 - stable/15 - rtld: allow dlopen("#/") List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@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/stable/15 X-Git-Reftype: branch X-Git-Commit: 8fb16a5c7f81121a68b5aa185d70f7fdcb228da5 Auto-Submitted: auto-generated Date: Thu, 09 Apr 2026 08:25:47 +0000 Message-Id: <69d7628b.3fa95.39af2d93@gitrepo.freebsd.org> The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=8fb16a5c7f81121a68b5aa185d70f7fdcb228da5 commit 8fb16a5c7f81121a68b5aa185d70f7fdcb228da5 Author: Konstantin Belousov AuthorDate: 2026-03-29 22:45:49 +0000 Commit: Konstantin Belousov CommitDate: 2026-04-08 18:22:39 +0000 rtld: allow dlopen("#/") (cherry picked from commit ffbf3fecdeffa17c0745e7ed342989acb620d68e) --- lib/libc/gen/dlopen.3 | 14 ++++++++++++ libexec/rtld-elf/rtld.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3 index 340545114114..2f10c17a4f53 100644 --- a/lib/libc/gen/dlopen.3 +++ b/lib/libc/gen/dlopen.3 @@ -164,6 +164,20 @@ Symbols from the loaded library are put before global symbols when resolving symbolic references originated from the library. .El .Pp +A special syntax for the +.Fa path +is supported, in the form of +.Dl #number/name . +The +.Ql number +should be a decimal number, which references an open file descriptor, +and which must be also listed in the environment variable +.Ev LD_LIBRARY_PATH_FDS . +In this case, the linker tries to load an object that can be opened by +.Ql openat(number, path, O_RDONLY) . +This feature is only available to trusted processes, i.e., +the activated image must be not set-uid or set-gid. +.Pp If .Fn dlopen fails, it returns a null pointer, and sets an error condition which may diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 9e64d1bf8aee..db5d22dfefdb 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -178,6 +178,7 @@ static int symlook_obj1_sysv(SymLook *, const Obj_Entry *); static int symlook_obj1_gnu(SymLook *, const Obj_Entry *); static void *tls_get_addr_slow(struct tcb *, int, size_t, bool) __noinline; static void trace_loaded_objects(Obj_Entry *, bool); +static int try_fds_open(const char *name, const char *path); static void unlink_object(Obj_Entry *); static void unload_object(Obj_Entry *, RtldLockState *lockstate); static void unref_dag(Obj_Entry *); @@ -2877,9 +2878,12 @@ load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags) * using stat(). */ if ((fd = open(path, O_RDONLY | O_CLOEXEC | O_VERIFY)) == -1) { - _rtld_error("Cannot open \"%s\"", path); - free(path); - return (NULL); + fd = try_fds_open(path, ld_library_dirs); + if (fd == -1) { + _rtld_error("Cannot open \"%s\"", path); + free(path); + return (NULL); + } } } else { fd = fcntl(fd_u, F_DUPFD_CLOEXEC, 0); @@ -3588,6 +3592,53 @@ rtld_nop_exit(void) { } +/* + * Parse string of the format '#number/name", where number must be a + * decimal number of the opened file descriptor listed in + * LD_LIBRARY_PATH_FDS. If successful, tries to open dso name under + * dirfd number and returns resulting fd. + * On any error, returns -1. + */ +static int +try_fds_open(const char *name, const char *path) +{ + const char *n; + char *envcopy, *fdstr, *last_token, *ncopy; + size_t len; + int fd, dirfd, dirfd_path; + + if (!trust || name[0] != '#' || path == NULL) + return (-1); + + name++; + n = strchr(name, '/'); + if (n == NULL) + return (-1); + len = n - name; + ncopy = xmalloc(len + 1); + memcpy(ncopy, name, len); + ncopy[len] = '\0'; + dirfd = parse_integer(ncopy); + free(ncopy); + if (dirfd == -1) + return (-1); + + envcopy = xstrdup(path); + dirfd_path = -1; + for (fdstr = strtok_r(envcopy, ":", &last_token); fdstr != NULL; + fdstr = strtok_r(NULL, ":", &last_token)) { + dirfd_path = parse_integer(fdstr); + if (dirfd_path == dirfd) + break; + } + free(envcopy); + if (dirfd_path != dirfd) + return (-1); + + fd = __sys_openat(dirfd, n + 1, O_RDONLY | O_CLOEXEC | O_VERIFY); + return (fd); +} + /* * Iterate over a search path, translate each element, and invoke the * callback on the result.