Live data from Hacker News

Why bother with argv[0]?

wietzebeukema.nl

171–180 of 277 posts

Re: Why bother with argv[0]?

#171
post #130

Earlier quoted context omitted.

`busybox whoami` is probably fine, but having to write `busybox ls`, `busybox grep`, `busybox cp` etc. would get tedious quickly. Shell aliases don't solve all problems, even if you do: alias rm="busybox rm" alias xargs="busybox xargs" # etc. you still have to write `xargs -exec busybox rm`, because xargs won't use the shell alias. But the main problem with this approach is that POSIX and LSB require certain binaries…

Well /bin/sh is also busybox, so I think you'd need #!/bin/busybox sh exec /bin/busybox ls ?

Great point!

Actually this observation invalidates the whole setup. Because even though you could define /bin/sh itself as:

    #!/bin/busybox sh
    exec /bin/busybox sh
Then you still cannot use #!/bin/sh in any other shell scripts, because for historical reasons the interpreter of a script is not allowed to be another interpreted script, it must be a binary. So /bin/sh pretty much has to be an actual binary.

Re: Why bother with argv[0]?

#172
post #73

If nothing else, argv[0] is useful for producing error messages that indicate the name of the executable that is outputting the message. It's probably a good idea to not have it settable to other values by the invoking process, as is generally the case on Windows (ignoring its Posix subsystem here).

> It's probably a good idea to not have it settable to other values by the invoking process, as is generally the case on Windows (ignoring its Posix subsystem here).

Well there is an use case that I sometime use for setting argv[0]. Consider you want to run yourself as a subprocess. Why you want to do that? There are plenty of reasons, but in general the thing is that doing things after a fork() is not safe under some circumstances and thus sometimes you also want to exec yourself.

A technique is to then call yourself using another name in argv[0] for then in the main take a different flow from the normal command line parting, without adding an argument that the user can specify if it know that it exists.

Yes, I know that there are a ton of other methods to do the same thing (perhaps an environment variable, for example), but I find the method of argv[0] quite nice and simple to be fair.

Re: Why bother with argv[0]?

#173

So obviously claiming that there's no good reason for process to read argv[0] is either demonstrating the author's ignorance or needs a much stronger defense; I'd be fascinated to hear how they think busybox should work on an OpenWrt box with a 16MB root filesystem. However , I am willing to consider the discussion about whether there could be merit to restricting the ability to write that value; I could imagine a sy…

Not an author, but there's a good alternative. If busybox was edited to ignore argv[2], then applets could be called via shebangs, instead of symlinks: $ echo '#!/path/to/busybox echo' > myecho $ chmod +x myecho $ ./myecho 123 ./myecho 123 Right now this doesn't work properly, because "./myecho" (argv[0]) gets placed into argv[2] of the process. Otherwise, this technique IMHO is better than symlinks: - Each applet us…

I was going to say it'd be easier to have a single script, eg

    #!/bin/sh
    busybox $0 $@
and then every command required could just be a hardlink to the same script, instead of replicating it over and over again for hardcoded command names.

Then I realised the whole point is to posit a world where $0 doesn't exist, and we're not allowed to be clever about it.

Re: Why bother with argv[0]?

#174

> “Should a program be allowed to behave differently based on its name?” I don’t see why not. It’s allowed to behave differently based on the arguments that follow it. I personally think the genericity of including the program name itself as one of its own calling arguments is really meta cool.

There are also multiple reasons for a program to read its own executable.

- Decompressing and inflating a compressed binary block with a generic decompressor at the top (e.g. a bash or python script with a binary blob at the end)

- Checksumming its own executable (skipping the checksum string) to resist virus infection. Not bulletproof but viruses aren't usually smart enough to circumvent this

Re: Why bother with argv[0]?

#176
post #155

Earlier quoted context omitted.

> highlighting a problem exists Coding bugs into your programs is not a problem it’s a bug. None of the weird arg[0] examples can happen on the shell (without escaping), only when using system calls. The more I read the article the more I feel this is a reaction to a behavior the author did not expect and fancy them as smart therefore the last 20 years of use age of this feature are obviously wrong.

> None of the weird arg[0] examples can happen on the shell (without escaping), only when using system calls. $ help exec [...] Options: -a name pass NAME as the zeroth argument to COMMAND Even in shell, you can explicitly specify the argv[0] when running an executable.

Not in all shells, but in some exec is a pass through to the system call …

Bash is a language, so again we are telling the stream to do something silly and calling it out had a security problem.

The issue is not arg[0] but uninformed expectations on how these systems work.

Relying on the program/command name for security and not the executable path is a bug.

Furthermore if a bad actor has enough access to run exec you probably are in a bad way.

The whole post also seems to not understand that both windows and linux have ways to change this display after the executable is running via SetConseTitle and prctl or simply modify arg[0] directly.

Re: Why bother with argv[0]?

#177

Earlier quoted context omitted.

Well that would be inefficient. For each command you run the kernel has to read the file, detect that it has a shebang, parse the shebang line, and then finally load the actual executable in memory. That could be a performance problem, since busybox is used typically in embedded systems that doesn't have a lot of resources: imagine a shell script that runs a command in a loop, it has to do a lot of extra work. Finall…

I’m going to challenge you on the performance angle. Instead of doing the shebang line, it has to traverse the filesystem to resolve the link. I suspect that’s probably more expensive than parsing the shebang line. Indeed, a shell script that runs a command in a loop should have busybox detecting the built in command & executing it inline without spawning executables via the file system (this is common in bash as wel…

> Instead of doing the shebang line, it has to traverse the filesystem to resolve the link. I suspect that’s probably more expensive than parsing the shebang line.

I highly doubt that. Path traversal is one of the most optimized pieces of code in the Linux kernel, especially for commonly accessed places like /bin where everything is most likely already in the dentry cache. For the script with a shebang on the other hand it first has to read it from disk (or the page cache), then parse the path from it, and then do a path traversal anyway to find the referenced file.

Re: Why bother with argv[0]?

#178

Earlier quoted context omitted.

No you make this script: #!/bin/sh exec /bin/busybox cmp And place it at /usr/bin/cmp

So now to execute a program that could have been a direct run you have to fire up a shell, have it parse the file, and execute the instruction? Not really a great thing... Plus, you have to know the absolute path of the executable busybox, not something you always know in advance.

You're not wrong about the extra execution of shell, although a lightweight shell like ash or dash doesn't have a huge overhead.

But realistically, the only people that need to worry about the actual location of the busybox executable are the people who write the install script - it would take that as an argument or variable and spit out all the little scripts as an automated process. The current installer already has to do most of this work as part of setting up the relevant links anyway.

Re: Why bother with argv[0]?

#179

I also use argv[0] for the -h help text, to show examples how to use the command.

There is also a neat little BSD extension, also supported on a number of other Unix-like systems and GNU userspace (i.e. glibc, but also other libcs like Musl): extern char *__progname; which holds the program name without the (optional) invocation path in front of it. Basically the last path component of argv[0].

wattttt? nice thank you

Re: Why bother with argv[0]?

#180
post #65

Earlier quoted context omitted.

Those 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 h…

What’s the issue with using argv[0] as a way to spawn yourself? I don’t recall running into a lot of issues.

If it's a relative path, then changing the working directory will break (chdir("/") is a very common tactic at the top of main()).

It's possible/desirable for the parent to change the PATH of a child process, particularly one that spawns other processes. So the argv[0] used to spawn the original process may be garbage for spawning children.

Similarly in any kind of chroot jail (which may or may not be docker these days), relative paths and PATH can be garbage even if they don't change.

The real problem is that I've seen in-house and open source frameworks/libraries that have a function like `get_executable_path` that reads `argv[0]` and this is just incorrect behavior. Spawning yourself is one of the less risky things you can do, but there are gotchas and a way to avoid them!

Post reply on HN