3
#!/bin/sh --

for set_trap_sig in HUP INT QUIT ALRM TERM; do
    trap -- '
        trap -- - '"${set_trap_sig:?}"' EXIT || exit "$?"
        kill -s '"${set_trap_sig:?}"' -- "$$" || exit "$?"' "$set_trap_sig"
done

sleep 15 || exit "$?"

Here's what happens when I send SIGINT to the script

user@hostname:/tmp$ ./script.sh
^C./script.sh: 3: ./script.sh: Syntax error: EOF in backquote substitution

This issue seems specific to dash. On ash, bash and ksh93 I do not get this error. This is particularly weird because my script does not even contain the backquote character.

If I remove the double quotes on the trailing $? on line 5 the error goes away.

Am I doing something stupid or is dash being retarded? And yes, I know I write scripts like a paranoid schizophrenic.

Edit: we have established this a very serious bug that affects even modern versions of Ubuntu and Debian. Does anyone know of a workaround?

  • 1
    Did you copy and paste your code into the question, or re-type it? I have no issues executing the code in the question using dash. – Kusalananda Apr 20 at 6:58
  • @Kusalananda this is reproducible, see my (not yet) answer – mosvy Apr 20 at 15:46
3

Here is a simplified testcase:

trap '
        trap    - HUP EXIT || exit "$?"
        kill -s HUP    "$$" || exit "$?" ' HUP INT
kill -HUP $$
$ dash dash-bug
dash-bug: 3: /home2/ahq/dash-bug: Syntax error: EOF in backquote substitution

Modifying the length or content of the quoted code may either "fix" the bug or produce different and interesting corruptions, with random bytes appearing out of nowhere.

This was caused by a use-after-free bug which was fixed since dash 0.5.9, but which is still present in the dash 0.5.8 from Debian 9.8 stable (stretch), Ubuntu 18.04 (bionic) and Ubuntu 18.10 (cosmic).

This is the commit which fixed it:

commit 6c3f73bc536082fec38bd36e6c8a121033c68835
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date:   Thu Oct 2 08:26:06 2014 +0800

    [EVAL] Fix use-after-free in dotrap/evalstring

    The function dotrap calls evalstring using the stored trap string.
    If evalstring then unsets that exact trap string then we will end
    up using freed memory.

    This patch fixes it by making evalstring always duplicate the string
    before using it.

    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

A work-around is to put the trap handler in a function -- so that no commands run after the trap has been unset try to use the action string after it has been freed:

sighandler(){
    trap - "$sig" EXIT || exit "$?"
    kill -s "$sig" "$$" || exit "$?"
}
for sig in HUP INT QUIT ALRM TERM; do
    trap "sig=$sig; sighandler" "$sig"
done

kill -s HUP "$$"
  • Does the error go away if you fix the nested single quotes? Something like trap " trap -- - \"'$s'\" EXIT || exit \"$?\" kill -s HUP -- \"$$\" || exit \"$?\"" "$s" or similar (sorry, I can't quite work out the right way). – terdon Apr 20 at 17:47
  • 1
    I'm just wondering if the issue is related to the nested single quotes is all. – terdon Apr 20 at 18:00
  • @mosvy Is there a workaround? This is all very unsettling to me. This bug is present in Ubuntu 14.04 and 16.04. In 18.04 I do not get the error but I see no evidence that the commit you reference has actually been applied yet when I look at the changelog. – Harold Fischer Apr 21 at 3:29
  • 1
    I'm not sure if there's any workaround; I'll have to check if putting the trap handler in a function completely bypasses this bug, but I cannot do that now (I'm on a phone). The dash from ubuntu 18.04 and 18.10 is the same 0.5.8 version so it's not fixed. Only the version from ubuntu 19.04 (disco) should be fixed. As all use-after-free bugs in scripting languages, this may be exploitable, though the impact should be pretty low. – mosvy Apr 21 at 12:16
  • @mosvy You mention 'random bytes appearing out of nowhere'. Does that mean there are cases where the bug surfaces and you wouldn't even notice? – Harold Fischer Apr 22 at 6:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.