How to mutate argv[0][0] to '@'?

I have a daemon that starts in initramfs but is being killed by systemd and I'd like it to not to be. Turns out that systemd has a way to prevent a process from being shutdown if the process mutates its own argv.

In this post about storage daemons it explains:

Processes (run by the root user) whose first character of the zeroth command line argument is @ are excluded from the killing spree, much the same way as kernel threads are excluded too. Thus, a daemon which wants to take advantage of this logic needs to place the following at the top of its main() function:

...
argv[0][0] = '@';
...

std::env::args and std::env::args_os are immutable as far as I can tell.

Does anyone know of a way to mutate argv as systemd would like?

2 Likes

You will probably have to avoid libstd's main wrapper and define the C main function yourself to get write access to argv. Something like:

#![no_main]

#[no_mangle]
fn main(argc: c_int, argv: *mut *mut c_char) -> c_int {
    // your code

    0 // success exit code
}

Be aware that this has will disable a couple of things libstd normally handles for you:

  • if stdin/stdout/stderr are closed, they aren't reopened as /dev/null by libstd. doesn't matter here as systemd will keep all of them open.
  • no SIGSEGV handler is registered to detect stack overflows and print a nice message. a stack overflow will SIGSEGV, but does not cause UB on x86_64 at least (and any kther arch where stack probing is enabled).
  • The SIGPIPE signal is not ignored, so attempting to write to a broken pipe will abort the program rather than return EPIPE.

If it matters you can still do all of these things manually.

5 Likes

According to the link you posted:

Since systemd v255, alternatively the SurviveFinalKillSignal=yes unit option can be set, and provides the equivalent functionality to modifying argv[0][0].

It seems this would be a better option in Rust. Seems v255 is the most recent version as of writing this (released in December 2023) so if you need to support slow moving non-rolling release distros that probably isn't an option currently.

That said it is really weird to me that Rust doesn't have an API to do this in the standard library.

1 Like

It’s not a direct answer to your question, but does it work to set argv[0] to something different when you run the program instead? For example, in bash you could write exec -a @myprogram /bin/myprogram.

1 Like

It would have to be unsafe and an extension trait, but yeah.

Related:

3 Likes

Great ! Thank you and really cool explainer!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.