💾 Archived View for thrig.me › blog › 2023 › 02 › 05 › wrapper-script-etiquette.gmi captured on 2023-09-08 at 16:29:29. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-04-19)

➡️ Next capture (2023-11-14)

-=-=-=-=-=-=-

Wrapper Script Etiquette

A wrapper script is one that makes various changes (flags, environment, logging, etc) and then runs some other program. Variations are possible.

pa

	ping -f "$@"

This is a script; it will run in certain contexts.

/blog/2023/01/12/sans-shebang-script.gmi

re

	#!/bin/sh
	ping -f "$@"

What ping are you really running? Are you sure things like duplicate environment variables are being handled? Does all your software get it right?

/blog/2022/12/14/duplicate-environment-variables.gmi

ci

	#!/bin/sh
	/sbin/ping -f "$@"

vo

	#!/bin/sh
	exec /sbin/ping -f "$@"

Discussion

Opinions vary here; the first (pa) lacks a shebang line so will only run in a shell context, system(3) and not an execv(3) call. You probably won't find many in favor of leaving off the shebang line. Some are content with the second version (re), and may claim that there is no reason to go beyond this. The third version (ci) fully qualifies the program to be run. There are several reasons to do this, one being "defense in depth" in the event an attacker somehow gains the ability to set the PATH under doas (or, worse, sudo) and thus can call some other ping, possibly one that they wrote, or a symlink to who knows what. Another reason is efficiency: why search PATH when /sbin/ping has always been /sbin/ping? Or, the principle of least surprise: this wrapper script only runs /sbin/ping, not something else. The final version (vo) adds an exec call, which means the shell script replaces itself with the given program instead of dangling around in memory. Granted, sh does not consume much in the way of resources compared to, say, a browser (that for security reasons must not be installed) but a pstree along the lines of

    ...
     | | \-+= 14511 jhqdoe /bin/sh ./foo ...
     | |   \-+- 35315 jhqdoe /bin/sh ./bar ...
     | |     \-+- 85977 jhqdoe /bin/sh ./baz ...
                ... (etc etc etc) ...

is not something I find tidy, especially when an exec call can usually replace all the dangle with the final script.

If I do maybe want to vary the program based on PATH, which would likely only be the case outside of doas (or, worse, sudo), I would probably settle for a hybrid wrapper of re and vo,

    #!/bin/sh
    exec someprog "$@"

though I rarely use PATH shenanigans like perlbrew does that makes different implementations available as the same name depending on the environment. I usually fully qualify paths in scripts by default--or rather the script is a template that has the path fully qualified when built for the system, e.g. a shebang line of "#!perl" is replaced on installation by the build system by the version of perl the script is built for:

    $ sed 1q ~/src/Game-Xomb/bin/xomb
    #!perl
    $ sed 1q `which xomb`
    #!/usr/bin/perl

This is probably yet another variation on the "static compile time vs. dynamic runtime" debate--"#!/usr/bin/env perl" would let you instead pick up on whatever is found in PATH, at the cost of looking around for that whatever. Others may want more complexity in the script--case statements to make it portable, etc--complexity that I would most likely push into the configuration management: on OpenBSD, install this script that only does exactly what it needs to. (If a /bin/sh script gets case statements or while loops or is more than about 20 lines long I start looking at a not-sh language to write it in.)

The 2009 macbook with a spinny metal disk that I used up until late 2022 could be hilariously slow, hence me generally looking for any sort of efficiency gain whatsoever. For example man(1) would take upwards of 200 to 300 milliseconds to show something after wandering through too many MANPATH directories (yes, I checked with dtrace) and executing too many commands; a Perl script could do much the same an order of magnitude faster, if one skipped all the bloat.

But why not just use sudo?

It is true that sudo lets you specify that a user can run "/sbin/ping -f *". It is also true that sudo lets attackers do various interesting things. The CVE list is long, and likely to grow. So the choices are use sudo and hope there are no exploits, or use doas and therefore you may need correctly written wrapper scripts that hopefully allow for no exploits. Or to write your own setuid program because sudo was unusable on RedHat Linux due to I forget what systems were throwing themselves in the way at the time. Or wait for someone to write a better operating system that is viable and popular enough to be used that has maybe some sort of capability system. You might need to wait for a while, given how entrenched LinuxacOSwindows are, but maybe something good might happen some day?

tags #security #sh #sudo #doas

bphflog links

bphflog index

next: A Tale Of Two Times