On Fri, Feb 21, 2025 at 12:14:51AM +0100, lorenzo wrote: > Hi Andrew, sorry for late reply: > > I was short on free time and also wanted to take some time to think > about this
No problem! > On Sun, 19 Jan 2025 19:31:55 +0000 Andrew Bower <and...@bower.uk> wrote: > > Hey Lorenzo, > > > > Would you consider adding a script to your runit package to help > > runscripts benefit from my new xchpst hardening tool while falling > > back to chpst-compatible options when it isn't installed, please? > > thanks for your work on this tool, I agree it would great to have > hardening as an available option for runit :) Thank you! I hope we can get one or two examples into trixie to inspire users (future contributors) who might want to develop their own runscripts, first for their stable installation. > I'm not sure we I will be able to get this right at the first attempt, > but let's see: > > I prefer to start with something simpler, I'm not sure it will work but: Understood. A reasonable position! > I had a look at runscripts and chpst is rarely used, often with one > option like 'chpst -uuser' or 'chpst -mNNN' or the like, so > for instance (stealing the idea from the power-profile-daemon chatting > we had), You are right. This does slightly call into question one of my core design principles, which was to be similar in form to and compatible with chpst - what is the point if chpst is rarely used? But we are here now and I think xchpst does basically do its job reasonably well! > * on the runscript side, in the exec line, we could do something like > > [if chpst is not used] > exec ${XCHPST:-} /bin/to/exec > > [if chpst is used, we hardcode it as fallback] > exec ${XCHPST:-chpst -u bob} /bin/to/exec > > now we need something to build $XCHPST when appropriate, > what about invoke-run? > > * in invoke-run we could do something like (not tested) > (it should probably no longer set -u) Taking advantage of invoke-run was one of my first thoughts (it could define something like <https://salsa.debian.org/abower/xchpst/-/blob/debian/latest/extra/xchpst-funcs.sh?ref_type=heads>, more or less the same as the implementation in this patch). > XCHPST="" > if [ -x /usr/bin/xchpst ]; then > if [ -r "${PWD}/xchopts" ] ; then > export XCHPST="xchpst $(cat ${PWD}/xchopts)" > fi > fi > > some thoughts (if it works): > > (positive aspects) > xchpst command line can be quite long, using the ${XCHPST:-} > variable keeps the exec line of runscripts more compact > (this is just my personal preference, not really a blocker); That's a fair criticism, which I had noticed. To help mitigate long lines we could: 1. Introduce short options for common things. I'm not sure about this though - I had left them clear to accomodate future chpst enhancements, like '-C', that I would want to support compatibly. 2. Come up with aggregate options for common combinations. 3. See discussion below around your idea - an options file. (Also in some of my own runscripts I have preferred to build a multi-line function in the shell script so that I can invoke it a second time with 'echo' for debug purposes, seeing the actual line executed.) > this way hardening can be enabled globally by installing > xchpst, and it can be disabled for a single service by > doing something (to be defined) on the xchopts file; > > it can be told by looking for the xchopts file if a service > directory has support for hardening (and xchpst options can be > extracted as well); This is an interesting idea. Two thoughts come to mind: 1) Does this pollute the runit environment? An extra file in the service directory that isn't used by runit itself? 2) I did actually wonder about using a file in the service directory myself. What would be better than populating a command line from a file, I think, would be for xchpst to take a file input which it can read instead of or to supplement command line options. This is better because cat'ing the file into command line options prevents spaces from being quoted and because it is a more indirect way of solving the problem. I think this could be a future enhancement for xchpst regardless of whether we use this approach in runscripts. > (negative aspects) > we add an XCHPST variable to the service environment, not a good thing > but hopefully the name is specific enough that it doesn't trigger > a behavior change in any existing daemon > > the command line is less transparent to the user: > people will ask " where does this XCHPST variable comes from?", > "what is for?", as they probably ask how files in /etc/default are > sourced, how the starting message is printed and so on, > they will really have to look at invoke-run manpage.. > > thoughts on the above? My main concern of this proposal is that it makes the standard path to reach the crux of a runscript more complicated - invoke-run is really useful but the more complicated and magical it is, the more opaque everything is for runit users, I feel. (Acknowledging that the extra complexity is intended to help people use my tool!) Have you seen what I have tried with a couple of runscript examples? https://salsa.debian.org/debian/runit-services/-/merge_requests/21/diffs HARDEN="xchpst --cap-bs-drop CAP_SYS_PTRACE --verbose" $HARDEN --exit || HARDEN="" exec $HARDEN ##bin## https://salsa.debian.org/debian/runit-services/-/merge_requests/19/diffs HARDEN="/usr/bin/xchpst --ro-sys --private-tmp --uts-ns" $HARDEN --exit && HARDEN="$HARDEN --verbose --" || HARDEN="" exec $HARDEN ##bin## $EXIMSERVICE -d These rely on nothing outside of themselves. They still suffer from the problem of not being able to quote space within arguments, although that shouldn't be a big issue. The '--exit' option was specifically added to return exit code 0 so that it could be used as a test for presence of xchpst - it can also check compatibility with the selected options. If I were to summarise my thoughts on the merits of the options: 1) xchpst.fake: PRO: least invasive to use, CON: magic 2) XCHPST env var CON: magic, CON: env var-based 3) HARDEN env var CON: env var-based Or is that not fair? 1 & 2 both concern me in that they make xchpst 'special', which I'm conscious of not necessarily being in the spirit of runit. Option 3 can always be upgraded because it is self-contained. I don't rule out any of these approaches yet!