Date: Fri, 5 Nov 2021 18:25:19 +0100 From: obiwac <obiwac@gmail.com> To: freebsd-current@freebsd.org Subject: Potential bug in the dynamic linker? Message-ID: <CAN8-kNW%2B97rLUpXBhWzqf8=WgFhs1gNWgc=xwKtUJgXDy-mGPQ@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
--00000000000011101005d00dee84 Content-Type: text/plain; charset="UTF-8" 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 "<unknown>" 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. 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; Should this not be ld_dynamic_weak = ld_get_env_var(LD_DYNAMIC_WEAK) != NULL; instead? Or is this actually intended and am I just not understanding the point of this? --00000000000011101005d00dee84--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAN8-kNW%2B97rLUpXBhWzqf8=WgFhs1gNWgc=xwKtUJgXDy-mGPQ>