The expected returned string is the first argument to the exec*() call, but it returns a random hardlink to that file instead. This prevents it from being used to detect how a program has been called and to select the dedicated behavior from a fat binary, that e.g. implements both POSIX and non-POSIX behavior. I came over that problem when calling the parallel version of SunPro Make as: /opt/schily/bin/dmake and readlink(/porc/curproc/file) returned /opt/schily/xpg4/bin/make
The canonical way to do this in FreeBSD is making use of elf_aux_info(3) with AT_EXECPATH. The information is copied to userspace in the program image during activation, but is not tracked by the kernel afterwards.
Solaris introduced getexecname() 23 years ago and I need/use it since 15 years. At that time, there was nothing similar in FreeBSD and procfs was the only way to go for porting. elf_aux_info() seems to be *really* new...I discovered after making the report. BTW: Solaris returns the expected result from procfs.
From the man page: #include <stdlib.h> const char *getexecname(void); ... If successful, getexecname() returns a pointer to the executables pathname; otherwise, it returns 0. ... The getexecname() function obtains the executable pathname from the AT_SUN_EXECNAME aux vector. These vectors are made available to dynamically linked processes only. It seems like we could also add getexecname as a slightly more convenient interface than elf_aux_info.
Implementing getexecname() would be an improvement as it does not need to use a private buffer and in many cases requires strdup() even though the string is on the stack anyway.
A commit references this bug: Author: tobik Date: Fri Jul 24 15:50:57 UTC 2020 New revision: 543251 URL: https://svnweb.freebsd.org/changeset/ports/543251 Log: lang/rust-nightly: Attempt to fix intermittent "can't find crate for `std`" build failures The location of rustc (found via env::current_exe()) is used to find the right libstd. However it might have been "copied" by creating a hard link to the new location instead. Like /proc/curproc/file, KERN_PROC_PATHNAME (used internally by current_exe()) can return any of the file's multiple paths. Most of the time it returns the right rustc path and the build will succeed but occasionally it will return the "wrong" path and the build fails with: error[E0463]: can't find crate for `std` If this is right a viable workaround should be to never create hard links during the build, so let's try that. Also drop the related llvm-config-wrapper workaround. PR: 248184 Changes: head/lang/rust-nightly/files/patch-src_bootstrap_lib.rs head/lang/rust-nightly/files/patch-src_bootstrap_native.rs
(In reply to Conrad Meyer from comment #1) The problem is also present with AT_EXECPATH. AT_EXECPATH doesn't really make a difference if the wrong name is copied to userspace in the first place. $ freebsd-version 13.0-RELEASE-p4 $ cat execpath.c #include <sys/auxv.h> #include <limits.h> #include <stdio.h> int main(int argc, char *argv[]) { char pathname[PATH_MAX]; elf_aux_info(AT_EXECPATH, pathname, PATH_MAX); puts(pathname); return 0; } $ make execpath $ ln -f execpath tmp/execpath $ ./execpath /home/tobias/execpath $ ./tmp/execpath /home/tobias/tmp/execpath $ ./execpath # I'd expect this to return /home/tobias/execpath again but: /home/tobias/tmp/execpath Now I'm coming back to this because lang/rust uses hardlinks in the build by default. We have disabled this since it caused intermittent build failures because env::current_exe (uses kern.proc.pathname.-1 sysctl internally) might returns the wrong pathname (one of the hardlinks) sometimes and rustc fails to find the right std crate. This is my working theory anyway. It's difficult to trigger the problem on my package builder. I was going to experiment with switching it over to AT_EXECPATH but I guess that will make no difference because of the current behavior of it. If getexecname() would be just a wrapper for elf_aux_info(AT_EXECPATH) then it wouldn't solve the problem either. Any suggestions what we should use instead of kern.proc.pathname, AT_EXECPATH, or /proc/curproc/file?
https://reviews.freebsd.org/D32611
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=0c10648fbb758bb76fd29330b7fe1bc519252325 commit 0c10648fbb758bb76fd29330b7fe1bc519252325 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-10-23 00:24:08 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-10-28 17:49:31 +0000 exec: provide right hardlink name in AT_EXECPATH For this, use vn_fullpath_hardlink() to resolve executable name for execve(2). This should provide the right hardlink name, used for execution, instead of random hardlink pointing to this binary. Also this should make the AT_EXECNAME reliable for execve(2), since kernel only needs to resolve parent directory path, which should always succeed (except pathological cases like unlinking a directory). PR: 248184 Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32611 sys/kern/kern_exec.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=ee92c8a842d61ffda8d111e1b0e398085c5bfb3a commit ee92c8a842d61ffda8d111e1b0e398085c5bfb3a Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-10-23 19:01:37 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-10-28 17:50:02 +0000 sysctl kern.proc.procname: report right hardlink name PR: 248184 Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32611 sys/kern/kern_proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=e5248548f95ff1c89667847e0d945dea38adeca7 commit e5248548f95ff1c89667847e0d945dea38adeca7 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-10-29 01:43:32 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-10-31 01:05:14 +0000 procfs: return right hardlink from /proc/curproc/file Use proc_get_binpath() to get the hardlink right. PR: 248184 Reviewed by: emaste, markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32738 sys/fs/procfs/procfs.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/ports/commit/?id=d5f09dc31fcfdb77b69c86b9093bf67ec67653d9 commit d5f09dc31fcfdb77b69c86b9093bf67ec67653d9 Author: Tobias Kortkamp <tobik@FreeBSD.org> AuthorDate: 2021-10-19 10:27:40 +0000 Commit: Tobias Kortkamp <tobik@FreeBSD.org> CommitDate: 2021-10-31 18:20:54 +0000 lang/rust-nightly: Update to 1.58.0.20211030 Make the no-hardlinks-patches conditional and move them to files/no-hardlinks. Newer kernels should return sane kern.proc.pathname values for hardlinks which will hopefully help avoid the intermittent "can't find crate for `std`" build failures we had on the package builders. Thanks to kib@ for fixing kernel behavior. Now let's see if it makes a difference for lang/rust-nightly. Changes: https://github.com/rust-lang/rust/compare/25ec8273855fde2d72ae877b397e054de5300e10...e249ce6b2345587d6e11052779c86adbad626dff PR: 248184 lang/rust-nightly/Makefile | 6 +++--- lang/rust-nightly/distinfo | 18 +++++++++--------- .../{ => no-hardlinks}/patch-src_bootstrap_lib.rs | 0 .../{ => no-hardlinks}/patch-src_bootstrap_native.rs | 0 ...r_rustc__target_src_spec_i686__unknown__freebsd.rs | 8 ++++---- lang/rust/Makefile | 19 +++++++++++++++++++ 6 files changed, 35 insertions(+), 16 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=f61af036ab291b558e8632bc58290b3321c2bafc commit f61af036ab291b558e8632bc58290b3321c2bafc Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-10-29 01:43:32 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-11-06 02:12:32 +0000 procfs: return right hardlink from /proc/curproc/file PR: 248184 (cherry picked from commit e5248548f95ff1c89667847e0d945dea38adeca7) sys/fs/procfs/procfs.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=ea4e8e191c0ecb12da16c34c2d14f04bc7f955c7 commit ea4e8e191c0ecb12da16c34c2d14f04bc7f955c7 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-10-23 19:01:37 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-11-06 02:12:32 +0000 sysctl kern.proc.procname: report right hardlink name PR: 248184 (cherry picked from commit ee92c8a842d61ffda8d111e1b0e398085c5bfb3a) sys/kern/kern_proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=a69fb7452ef97b5690f1811d4fb3b7b9f8ad78f8 commit a69fb7452ef97b5690f1811d4fb3b7b9f8ad78f8 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2021-10-23 00:24:08 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2021-11-06 02:12:31 +0000 exec: provide right hardlink name in AT_EXECPATH PR: 248184 (cherry picked from commit 0c10648fbb758bb76fd29330b7fe1bc519252325) sys/kern/kern_exec.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-)
I believe this has been fixed. Thanks.