1

This is based on another question of mine. I am trying to prevent executions of certain commands using a script. I got the script to work perfectly in interactive shells, but for noninteractive shells it doesn't prevent its execution.

/home/user/stop.sh (sourced in .bashrc)

#!/usr/bin/env bash
shopt -s extdebug; stop_cmd () {
    [ -n "$COMP_LINE" ] && return  # not needed for completion
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # not needed for prompt
    local this_command=$BASH_COMMAND;
    echo $this_command" Not Allowed";
    return 1
};
trap 'stop_cmd' DEBUG

/home/user/temp.sh

#!/usr/bin/env bash
ls

I used the BASH_ENV variable suggested by @Inian to get my script into script files that use non-interactive shells.

In a new shell

#:export BASH_ENV=/home/user/stop.sh
#:ls
ls Not Allowed --> This is because of the source in .bashrc
#:             --> Prompt appears. ls did not run
#:./temp.sh
./temp.sh: /usr/share/bashdb/bashdb-main.inc: No such file or directory
./temp.sh: warning: cannot start debugger; debugging mode disabled
ls Not Allowed  --> Because of the $BASH_ENV
Directory contents displayed  --> ls ended up running
#:             --> Prompt appears after executing temp.sh

But this behavior is not displayed if I source stop.sh within temp.sh directly and it works like a charm.

tripleee
  • 175,061
  • 34
  • 275
  • 318
Sam Thomas
  • 647
  • 7
  • 25
  • I did not do it! But can you explain how are you using `BASH_ENV` in your code above? and contents of the file passed to it – Inian Feb 08 '18 at 07:28
  • @Inian Sorry if it isn’t apparent.. let me edit the question. and I know you didn’t do it – Sam Thomas Feb 08 '18 at 07:31
  • @Inian Done editing the question – Sam Thomas Feb 08 '18 at 07:46
  • 1
    Griping about downvotes is a great way to attract more of them. This is not how it's properly supposed to work but unremarkable given the situation where you are asking for help and are still apparently learning the rules of this site. – tripleee Feb 08 '18 at 08:06
  • 3
    As an aside, `echo $this_command" Not Allowed";` looks odd. There is no particular reason to put the static string inside double quotes, but lots of reasons to have `$this_command` inside quotes. See also https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable – tripleee Feb 08 '18 at 08:09
  • @tripleee I apologize about that.. I'm just splitting my hair on why a source inside the script behaves so differently from $BASH_ENV – Sam Thomas Feb 08 '18 at 08:14
  • It looks like it loses the value of the `DEBUG` trap but it's still not clear where exactly this is happening or why the trap gets set to a file name which cannot be found, or where that file name is controlled. I think you need `set -T` but I don't know enough about `DEBUG` traps to really look properly into this. – tripleee Feb 08 '18 at 08:17
  • @tripleee By losing value.. you mean the return 1 value right? Or are you saying the trap isn't being invoked for you? – Sam Thomas Feb 08 '18 at 08:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164733/discussion-between-sam-thomas-and-tripleee). – Sam Thomas Feb 08 '18 at 08:21
  • 1
    I haven't tried to repro but it's looking like `trap 'stop_cmd' DEBUG` is not getting inherited. I'm speculating that `env` is the culprit here. – tripleee Feb 08 '18 at 08:21
  • Can you update the question to state that you're aware that this will be trivial to circumvent? This will help future readers who come across it. – that other guy Feb 08 '18 at 23:53
  • Well?  Any comment on my answer? – G-Man Says 'Reinstate Monica' Feb 14 '18 at 21:03

2 Answers2

1
  1. The simplest way to prevent users from running any command is to not give them accounts.  (You say you want to “prevent executions of certain commands”, but your stop.sh prevents all commands.  This makes your question somewhat hard to understand.)
  2. The simplest way to prevent users from running certain programs is to chmod them to 700.  If designated users are required to be able to run the program, give them access with ACLs.  (If only a few users are required to be blocked, you may be able to do that with ACLs, but that might be unreliable.)

    Your approach is going to be very hard to get right.  Assuming that you really want to prevent people from running ls (really?), do you plan on handling things like

    cp /bin/ls ls_copy
    ./ls_copy
    

    or

    ln -s /bin/ls ls_link
    ./ls_link
    

    ?

  3. I learned today that bash has a debug mode.  I don’t know much about it, but I’ve discovered experimentally that, when a bash process starts and reads a BASH_ENV file that sets extdebug, it (the bash shell) tries to read /usr/share/bashdb/bashdb-main.inc.  (This path, apparently, is hard-coded in /bin/bash.)  This should come as no surprise to you, as you got an error message naming that file.  Evidently there was a problem reading that file.

    This does not happen if you set extdebug and/or do trap some_command DEBUG in the script (directly or via source); I don’t know why.  (Here and here are a couple of references about the bash debugger.)

    Suggestions:

    • If the /usr/share/bashdb directory doesn’t exist, or it does but the bashdb-main.inc file doesn’t exist, create them (empty file).
    • If /usr/share/bashdb/bashdb-main.inc exists, rename it to a backup name.  In particular, this will be useful if bashdb-main.inc is a symbolic link to a file that doesn’t exist.
    • If /usr/share/bashdb/bashdb-main.inc exists, and you try the second bullet above (rename the file) and that doesn’t work, try the first bullet (create an empty file).
  4. By doing the above (renaming /usr/share/bashdb/bashdb-main.inc), I was able to get your command-execution-prevention trick working.

  • Hi @G-Man, I was working on this and spoke to Chet Ramey along the way and hence it took a while. Sorry about the late reply. 1 (my code is just an example) and 2 does not serve my purpose since I wish to prevent cases where the command is allowed to be used but not certain Params passed to that command. Eg: ls is allowed but not ls -al. Let’s get down to your suggestion on 3. That file is used by the package bashdb and doing it your way prevents a person from actually using bashdb. Also when bashdb is in place all the traps are removed. – Sam Thomas Feb 14 '18 at 21:12
  • If the traps are removed it’s absolutely fine with me since they won’t be able to debug my trap ! Haha – Sam Thomas Feb 14 '18 at 21:16
0

According to Chet Ramey, shopt -s extdebug is internally equally to — debugger. And if bash doesn’t find a debugger during its initialization it unsets this option essentially making my return 1 useless. The above said only happens in non interactive mode since interactive shells can’t be debugged (hence the flags are not unset). And this explains clearly the behaviors stated in my question. So in scripts that should use my trap would need to reset shopt - s extdebug at the very top.

Sam Thomas
  • 647
  • 7
  • 25