6 ms·
Also if you want a program to call itself, which is sometimes useful, this way lets you actually call the same program, rather than assuming the name and path.
by mistercow 2y ago
Also if you want a program to call itself, which is sometimes useful, this way lets you actually call the same program, rather than assuming the name and path.
- akira2501 2y agoBeware TOC TOU problems when doing this.
- fallingsquirrel 2y agoYou can do this without assuming the name by execing /proc/$PID/exe. Then you're not vulnerable to the argv[0] spoofing described in the article. (But of course since argv[0] does exist, you should set it properly and pass through your own argv[0] unchanged.)
- duped 2y agoDon't do this - if you (reliably) want the path to the current executable there is no portable way to do it, but on Linux you need to readlink /proc/self/exe and on MacOS you call _NSGetExecutablePath. I forget the API on Windows.
- flohofwoe 2y agoThere's also this very handy and tiny cross-platform library: https://github.com/gpakosz/whereami https://github.com/gpakosz/whereami
- theamk 2y agoI would not say it in such absolute way - /proc/self/exe has downsides as well. As this resolves all symlinks, so this breaks all the things that depend on argv[0], like nice help messages, python's virtualenv, name-based dispatch, and seeing if the program which was executed via symlink or not. A lot of times you know you never called chdir(), in which case I'd actually recommend executing argv[0], as this is nicest thing for admins. If you are really worried, you can use /proc/self/exe for progname and pass argv[0] as-is, but that's overkill a lot of times.
- mbrumlow 2y agoI think you forget the exec system call’s first argument is a path to an executable, followed by an array of arguments, where arg[0] lives. I can’t find issue with exec(“/proc/self/exe”, [ program , … ).
- alerighi 2y agoWell, it could be for example that /proc is not mounted. A lot of software breaks for this, while really there is no need for it to be so. Also that approach only works on Linux, if you want to write a portable software what you do?
- mbrumlow 2y agoI am mainly pointing out that arg[0] is still valid. Writing portable software is an entirely different topic.
- duped 2y agoThose are all cases where you're using argv[0] as an argument to the program where it's appropriate. Using it as the path to spawn a child process is incorrect. You're free to re-use it as an argument. I have fixed enough software that made this mistake that I'm confident to be absolute about it. It's a very easy mistake to make but it's really annoying when software makes it and someone needs to deal with it at a higher level. It's better for developers to know that argv[0] isn't the path to the executable it's what was used to invoke the executable.
- sweetjuly 2y agoNote though that both of these solutions are racy and so should not be done if "someone symlinking really fast and swapping the binaries" is in your threat model. Linux proc/self is safe though, just not the result from readlink.
- duped 2y agoWell that's true, but also something that can't be addressed within a currently running process afaik.
- ForOldHack 2y agoFour cardinal sins of programming: 1. Self modifying code. ( The word 'recalcitrant' comes to mind. 2. calling your own program to execute itself. 3. Interrupting the flow of control with a jump. 4. Non-graceful exit. 5. Renaming 'hack' as 'vi' or 'ps'
- SoftTalker 2y agoThere's no guarantee that the name and the path are still the same executable that is running, or that they even exist anymore.
- mistercow 2y agoI mean sure. All software is built on assumptions. Make sure the assumptions you’re making are appropriate in context.
- wang_li 2y agoIn most of the variants of exec*() there are separate arguments for the thing to be executed and the *argv[] list. Argv[0] being the executable is just a convention. In perl $ARGV[0] is the first positional parameter. In $ perl myscript.pl a b c $ARGV[0] is "a".
- wongarsu 2y agoUnless you are on Windows
- glandium 2y agoYou can actually rename an executable that is running, on Windows. That's a way to handle self updates: rename the executable, create its replacement, execute the new one to make it remove the old executable.
- deleted 2y ago[deleted]