From nobody Sat Nov 06 03:55:49 2021 X-Original-To: freebsd-current@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 6F435184CD52 for ; Sat, 6 Nov 2021 03:55:59 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (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 mx1.freebsd.org (Postfix) with ESMTPS id 4HmNp71Tx5z4lhW for ; Sat, 6 Nov 2021 03:55:59 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from tom.home (kib@localhost [127.0.0.1]) by kib.kiev.ua (8.16.1/8.16.1) with ESMTPS id 1A63tnCW049039 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NO); Sat, 6 Nov 2021 05:55:53 +0200 (EET) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.10.3 kib.kiev.ua 1A63tnCW049039 Received: (from kostik@localhost) by tom.home (8.16.1/8.16.1/Submit) id 1A63tnx0049038; Sat, 6 Nov 2021 05:55:49 +0200 (EET) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Sat, 6 Nov 2021 05:55:49 +0200 From: Konstantin Belousov To: obiwac Cc: freebsd-current@freebsd.org Subject: Re: Potential bug in the dynamic linker? Message-ID: References: List-Id: Discussions about the use of FreeBSD-current List-Archive: https://lists.freebsd.org/archives/freebsd-current List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-current@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,FREEMAIL_FROM, NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.5 X-Spam-Checker-Version: SpamAssassin 3.4.5 (2021-03-20) on tom.home X-Rspamd-Queue-Id: 4HmNp71Tx5z4lhW X-Spamd-Bar: ---- Authentication-Results: mx1.freebsd.org; none X-Spamd-Result: default: False [-4.00 / 15.00]; REPLY(-4.00)[] X-ThisMailContainsUnwantedMimeParts: N On Fri, Nov 05, 2021 at 06:27:33PM +0100, obiwac wrote: > Let me preface this by saying that I am in no way knowledgeable enough > regarding the FreeBSD dynamic linker to know whether or not this is > infact a bug or intended behaviour. > > This program I'm working on, when compiled for FreeBSD, calls > fdlopen(3) to load a dynamic library from memory. This is how I'm > doing that more specifically: > > // void* lib_bin, size_t lib_len > > int fd = shm_open(SHM_ANON, O_RDWR, 0); > ftruncate(fd, lib_len); > > void* lib_mem = mmap(NULL, lib_len, PROT_WRITE, MAP_SHARED, fd, 0); > memcpy(lib_mem, lib_bin, lib_len); > > munmap(lib_mem, lib_len); > > void* lib = fdlopen(fd, RTLD_LAZY); > close(fd); > > Running this on FreeBSD 13 works fine, FreeBSD 14, however, spits out > this error: > > Cannot fstatfs "" > > Digging around, I find, in libexec/rtld-elf/rtld.c: > > /* > * but first, make sure that environment variables haven't been > * used to circumvent the noexec flag on a filesystem. > */ > if (dangerous_ld_env) { > if (fstatfs(fd, &fs) != 0) { > _rtld_error("Cannot fstatfs \"%s\"", printable_path(path)); > return NULL; > } > if (fs.f_flags & MNT_NOEXEC) { > _rtld_error("Cannot execute objects on %s", fs.f_mntonname); > return NULL; > } > } > > And this is the first thing that seems weird to me. Why is it calling > fstatfs(3) before checking if the file descriptor doesn't necessarily > refer to a file which resides on a physical filesystem? It doesn't say > so on the manpage, but, again, digging around, that's what the error > returned by fstatfs(3), EINVAL, supposedly means. Exactly what is missing from the man page? How do you propose to check for MNT_NOEXEC without querying it with fstatfs()? What could be improved there, IMO, is that fstatfs(2) error is considered fatal, while it is arguably a reason to not check for MNT_NOEXEC. As you pointed out, fd might be not a file. I will commit this change shortly. > > Secondly, why then is dangerous_ld_env even set in the first place? > Well, as of this commit (https://reviews.freebsd.org/D26352): > > ld_dynamic_weak = ld_get_env_var(LD_DYNAMIC_WEAK) == NULL; > > ... > > dangerous_ld_env = libmap_disable || libmap_override != NULL || > ld_library_path != NULL || ld_preload != NULL || > ld_elf_hints_path != NULL || ld_loadfltr || ld_dynamic_weak; This should by !ld_dynamic_weak. I will commit the fix shortly. > > Should this not be > > ld_dynamic_weak = ld_get_env_var(LD_DYNAMIC_WEAK) != NULL; No, this is wrong. You are flipping the meaning of the env variable. > > instead? Or is this actually intended and am I just not understanding > the point of this?