Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenBSD: current_exe() fails when bin resolved through $PATH #60560

Open
kpcyrd opened this issue May 5, 2019 · 3 comments
Open

OpenBSD: current_exe() fails when bin resolved through $PATH #60560

kpcyrd opened this issue May 5, 2019 · 3 comments
Labels
C-bug Category: This is a bug. O-openbsd Operating system: OpenBSD T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@kpcyrd
Copy link

kpcyrd commented May 5, 2019

I've noticed std::env::current_exe() on openbsd depends on argv[0], which means the resolution only works if the binary was started with a relative or absolute path, but not when it was resolved by the shell using $PATH.

#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
let mut mib = [libc::CTL_KERN,
libc::KERN_PROC_ARGS,
libc::getpid(),
libc::KERN_PROC_ARGV];
let mib = mib.as_mut_ptr();
let mut argv_len = 0;
cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_len,
ptr::null_mut(), 0))?;
let mut argv = Vec::<*const libc::c_char>::with_capacity(argv_len as usize);
cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _,
&mut argv_len, ptr::null_mut(), 0))?;
argv.set_len(argv_len as usize);
if argv[0].is_null() {
return Err(io::Error::new(io::ErrorKind::Other,
"no current exe available"))
}
let argv0 = CStr::from_ptr(argv[0]).to_bytes();
if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
crate::fs::canonicalize(OsStr::from_bytes(argv0))
} else {
Ok(PathBuf::from(OsStr::from_bytes(argv0)))
}
}
}

@jonas-schievink jonas-schievink added C-bug Category: This is a bug. O-openbsd Operating system: OpenBSD T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels May 5, 2019
@kpcyrd
Copy link
Author

kpcyrd commented May 5, 2019

Note that the code in rust upstream silently defaults to a wrong path (simply the program name in the current working directory), while openbsd downstream applies a patch to make this fail explicitly:

$OpenBSD: patch-src_libstd_sys_unix_os_rs,v 1.10 2019/03/11 19:13:40 semarie Exp $
argv0 isn't suitable as current_exe() in all cases.
Index: src/libstd/sys/unix/os.rs
--- src/libstd/sys/unix/os.rs.orig
+++ src/libstd/sys/unix/os.rs
@@ -273,13 +273,14 @@ pub fn current_exe() -> io::Result<PathBuf> {
         argv.set_len(argv_len as usize);
         if argv[0].is_null() {
             return Err(io::Error::new(io::ErrorKind::Other,
-                                      "no current exe available"))
+                                      "no current exe available (null)"))
         }
         let argv0 = CStr::from_ptr(argv[0]).to_bytes();
         if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
             ::fs::canonicalize(OsStr::from_bytes(argv0))
         } else {
-            Ok(PathBuf::from(OsStr::from_bytes(argv0)))
+            Err(io::Error::new(io::ErrorKind::Other,
+                               "no current exe available (short)"))
         }
     }
 }

Unfortunately this patch doesn't give me the real path either.

@reynoldsbd
Copy link

Looks like the person who added this patch is on GitHub. @semarie can you share some context for why this patch is necessary on OpenBSD?

@semarie
Copy link
Contributor

semarie commented Aug 22, 2020

under OpenBSD, you have no standard way to retreive the path of the running executable.

basically it means env::current_exe() couldn't return useful thing on OpenBSD, but at design time it was just ignored (as 1-tier platform provides mostly accurate value in usual cases).

the patch on the OpenBSD ports is here to hard fail instead of silenciously use a potential wrong path.

bket added a commit to bket/bupstash that referenced this issue Jan 7, 2021
OpenBSD does not offer a standard way to retrieve the path of the
running executable. This means that env::current_exe() cannot return
anything useful when bupstash is resolved through $PATH resulting in a
hard fail (rust-lang/rust#60560):

```
$ bupstash version
bupstash-0.6.3
$ export BUPSTASH_REPOSITORY=/tmp/xxx
$ rm -rf $BUPSTASH_REPOSITORY; bupstash init; echo $?
bupstash init: no current exe available (short)
1
$ rm -rf $BUPSTASH_REPOSITORY; ./bupstash init; echo $?
0
```
Instead use progname via std::env::args() on OpenBSD:

```
$ export BUPSTASH_REPOSITORY=/tmp/xxx
$ rm -rf $BUPSTASH_REPOSITORY; bupstash init; echo $?
0
$ rm -rf $BUPSTASH_REPOSITORY; ./bupstash init; echo $?
0
```
andrewchambers pushed a commit to andrewchambers/bupstash that referenced this issue Jan 7, 2021
OpenBSD does not offer a standard way to retrieve the path of the
running executable. This means that env::current_exe() cannot return
anything useful when bupstash is resolved through $PATH resulting in a
hard fail (rust-lang/rust#60560):

```
$ bupstash version
bupstash-0.6.3
$ export BUPSTASH_REPOSITORY=/tmp/xxx
$ rm -rf $BUPSTASH_REPOSITORY; bupstash init; echo $?
bupstash init: no current exe available (short)
1
$ rm -rf $BUPSTASH_REPOSITORY; ./bupstash init; echo $?
0
```
Instead use progname via std::env::args() on OpenBSD:

```
$ export BUPSTASH_REPOSITORY=/tmp/xxx
$ rm -rf $BUPSTASH_REPOSITORY; bupstash init; echo $?
0
$ rm -rf $BUPSTASH_REPOSITORY; ./bupstash init; echo $?
0
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. O-openbsd Operating system: OpenBSD T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants