Opened 10 years ago

Last modified 10 years ago

#254 new defect

Drive a rusty spork through mbash, repeatedly, and dump it in a gutter.

Reported by: andersk Owned by:
Priority: normal Milestone:
Component: internals Keywords:
Cc:

Description

mbash breaks gdb:

$ echo 'int main() {return 0;}' | gcc -g -xc -

$ gdb ./a.out
(gdb) break main
Breakpoint 1 at 0x400478: file <stdin>, line 1.
(gdb) run
Starting program: /tmp/andersk/a.out
During startup program exited normally.

$ SHELL=/bin/bash gdb ./a.out
(gdb) break main
Breakpoint 1 at 0x400478: file <stdin>, line 1.
(gdb) run
Starting program: /tmp/andersk/a.out 

Breakpoint 1, main () at <stdin>:1
1	<stdin>: No such file or directory.
	in <stdin>

Change History (2)

comment:1 Changed 10 years ago by geofft

The zephyr logs from instance suexec on 3 March 2010 are enlightening. The current code for mbash is this:

#!/bin/sh

/bin/bash --rcfile /usr/local/etc/mbashrc "$@"

Apart from the bug Anders mention here here (that it runs your "real" shell as a subshell), the other issue is that it unconditionally calls /bin/bash and doesn't preserve attributes such as whether the bash you run is a login shell. So none of our shells are login shells, which gets confusing (and only somewhat less confusing because /etc/bashrc on Fedora happens to source /etc/profile.d/* with stdout silenced, which is a little bit of a questionable decision, but whatever).

The obvious approach is to put cd web_scripts (inside some conditional) in /etc/bashrc.d, and change people's shells to bash. However, there's the subtle side effect that the current scheme of --rcfile replaces .bashrc. In particular, without it,

  1. bash will attempt to source ~/.bashrc / ~/.bash_profile, and show an error. While the bash documentation implies that this is a bug, and that if those files aren't readable they shouldn't be sourced,
  2. mbashrc, in addition to doing cd web_scripts, also sources /etc/bashrc. If we get rid of it and let the attempt to read ~/.bashrc fail, then nothing will source that file.

So we can fix the bug in 1, patch it, and send it upstream, but dealing with 2 is complicated. Our only hook for non-login shells is bashrc or whatever else we specify as the rcfile.

I proposed replacing mbash with a C wrapper that just execs /bin/bash with --rcfile /usr/local/etc/mbashrc. Since it execs the resulting bash process, it should work fine, and this gives us the opportunity to set the --rcfile hook. I don't think there's an inherent reason to avoid the wrapper if we make the semantics work.

I don't see an alternative approach that reliably sources /etc/bashrc on every non-login shell. We could decide we don't care about /etc/bashrc at all, and only care about /etc/profile.d/scripts-accountadm running on login shells. But then we lose what we were trying to solve in March 2010.

We could also play silly tricks with sourcing /etc/bashrc from /etc/profile.d somehow, and avoiding the infinite recursion... I think Debathena plays these sorts of tricks.

comment:2 Changed 10 years ago by mitchb

Unfortunately, there are a couple problems with the proposed solutions for both halves of the problem.

With respect to (1) patching bash upstream to suppress the errors from unreadable ~/.bashrc or ~/.bash_profile, the man page does say that it will run commands from the first of them that's existent and readable. However, it doesn't say that you won't get an error about non-readability. In fact, though it's separated by several paragraphs, it actually says the opposite:

"""

The following paragraphs describe how bash executes its startup files. If any of the files exist but cannot be read, bash reports an error.

"""

With respect to (2) replacing mbash with a C wrapper to exec /bin/bash (thus preserving whether it's a login shell) with --rcfile /usr/local/etc/mbashrc, the problem is that the .bashrc (which --rcfile replaces) does *not* run in a login shell. This is true even if you explicitly specify it with --rcfile. The only reason we're currently succeeding at having our mbashrc run is that none of our shells are login shells.

Note: See TracTickets for help on using tickets.