Jump to page: 1 2
Thread overview
[Issue 21656] [REG2.091] Wrong file read during exception stringification leads to SIGBUS
Feb 22, 2021
kinke
Feb 22, 2021
Vladimir Panteleev
Feb 22, 2021
Vladimir Panteleev
Feb 22, 2021
ZombineDev
Feb 22, 2021
Vladimir Panteleev
Feb 22, 2021
Jacob Carlborg
Feb 23, 2021
Vladimir Panteleev
Feb 23, 2021
Jacob Carlborg
Feb 23, 2021
kinke
Dec 07, 2021
Dlang Bot
Dec 13, 2021
Dlang Bot
February 22, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

kinke <kinke@gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kinke@gmx.net

--- Comment #1 from kinke <kinke@gmx.net> ---
This seems to boil down to the usage of `program_invocation_name` on Linux to obtain the name of the executable file (though that hasn't changed in the linked druntime PR). It's apparently just `argv[0]` and so not really robust. Not sure if BSD's `getprogname()` is better in this regard. Too bad `std.file.thisExePath()` is in Phobos and thus not usable.

--
February 22, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

--- Comment #2 from Vladimir Panteleev <dlang-bugzilla@thecybershadow.net> ---
(In reply to kinke from comment #1)
>  (though that hasn't changed in the linked druntime PR)

But, why would bisection point to that PR as the earliest point for the observed SIGBUS, then?

> Too bad `std.file.thisExePath()` is in Phobos and thus not usable.

I don't see why it couldn't be moved to Druntime. It looks like it would be a good fit.

--
February 22, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

--- Comment #3 from Vladimir Panteleev <dlang-bugzilla@thecybershadow.net> ---
BTW, not sure about other systems, but on Linux, reading /proc/self/exe is going to be more reliable than via thisExePath. The reason being that /proc/self/exe is a special directory entry which continues to be valid (openable) even when the target that it (as a symlink) is pointing at is gone. So, perhaps just moving thisExePath to Druntime is not the best option.

--
February 22, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |petar.p.kirov@gmail.com

--- Comment #4 from ZombineDev <petar.p.kirov@gmail.com> ---
Could we move it to druntime and then make it use `/proc/self/exe` on Linux?

--
February 22, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

--- Comment #5 from Vladimir Panteleev <dlang-bugzilla@thecybershadow.net> ---
It would have to be a different function. `thisExePath` returns a string, but what we really need is a file descriptor. (And, we can't return the string literal "/proc/self/exe" from `thisExePath` on Linux, that would break other uses such as reading files adjacent to the program's executable.)

--
February 22, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

Jacob Carlborg <doob@me.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |doob@me.com

--- Comment #6 from Jacob Carlborg <doob@me.com> ---
`thisExePath` uses `/proc/self/exe` on Linux, but it uses `readlink` to read out the path, instead of opening the actual file.

`getprogname` is no better than `program_invocation_name`. They have more or less the same semantics. `getprogname` returns what was stored by `setprogname`. This is what the man pages say about `setprogname`:

The setprogname() function sets the name of the program to be the last component of the progname argument.

The best would probably be to copy the implementation of `thisExePath`, but change it to open the file and return a file descriptor.

A file descriptor to the executable also seems to be available in the auxiliary vector on Linux [1]. This can be accessed with the function `getauxval` or directly after the `envp` parameter in the C main function. I see references to the auxiliary vector in *BSD systems as well. Might be worth checking out.

BTW, there does not seem to be a reliable way to get the path to the current executable on OpenBSD.

[1] http://articles.manugarg.com/aboutelfauxiliaryvectors.html [2] https://lwn.net/Articles/519085/

--
February 23, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

--- Comment #7 from Vladimir Panteleev <dlang-bugzilla@thecybershadow.net> ---
(In reply to Jacob Carlborg from comment #6)
> A file descriptor to the executable also seems to be available in the auxiliary vector on Linux [1]. This can be accessed with the function `getauxval` or directly after the `envp` parameter in the C main function. I see references to the auxiliary vector in *BSD systems as well. Might be worth checking out.

Interesting, though as far as I can see, that file descriptor is only available to interpreters, and is no longer there at the time that the interpreted program has begun execution. Otherwise, it would take up a file descriptor slot, and thus would be a very noticeable fourth addition to the standard stdin/stdout/stderr streams. So it doesn't look like we can use this unfortunately.

--
February 23, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

--- Comment #8 from Jacob Carlborg <doob@me.com> ---
You are right that the file descriptor (AT_EXECFD) won't work, I just tested that, it doesn't return a valid value. But, perhaps even better, it's possible to access the address of the program headers of the executable (AT_PHDR) [1]. Here's an experiment I did on Linux:

# cat main.d
import core.stdc.stdio;
import core.internal.elf.dl;

extern (C) ulong getauxval(ulong type);

void main()
{
    const aux = cast(void*) getauxval(3);
    const baseAddress = SharedObject.thisExecutable.baseAddress;
    printf("aux=%p baseAddress=%p diff=%ld\n", aux, baseAddress, aux -
baseAddress);
}

# dmd -run main.d
aux=0x55eb0f1e4040 baseAddress=0x55eb0f1e4000 diff=64

It returns a slightly different address than `SharedObject.thisExecutable.baseAddress`, but it's close enough that it cannot be a coincident. Perhaps someone with more knowledge of `core.internal.efl` can explain why the difference.

[1] https://man7.org/linux/man-pages/man3/getauxval.3.html

--
February 23, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

--- Comment #9 from kinke <kinke@gmx.net> ---
I've just hit a related issue, a regression in master which was unfortunately cherry-picked for LDC 1.25 final: https://github.com/dlang/druntime/pull/3382

The problem in this specific case was that the unittest process changes the working dir (unit-threaded SandBox) and then an exception is thrown. The executable can thus not be opened anymore, and no file/line infos are available (if it wouldn't segfault before). I guess this scenario is 1000x more likely than the executable file being in Nirvana at the time an exception is thrown, and a real problem.

--
December 07, 2021
https://issues.dlang.org/show_bug.cgi?id=21656

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull

--- Comment #10 from Dlang Bot <dlang-bot@dlang.rocks> ---
@kinke created dlang/druntime pull request #3643 "Fix Issue 21656 - Read correct ELF executable for DWARF file/line infos" fixing this issue:

- Fix Issue 21656 - Read correct ELF executable for DWARF file/line infos

  By porting Phobos' `thisExePath()` to druntime (for ELF platforms),
  in a `@nogc nothrow` fashion for low-level usage in exception
  backtraces.

https://github.com/dlang/druntime/pull/3643

--
« First   ‹ Prev
1 2