[PATCH] Fix hang if $OLDPWD points to inaccessible directory

classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka
Bash attempts to execute the stat syscall on the $OLDPWD variable on every
startup. This results in hard to diagnose hangs if the $OLDPWD variable
points to a directory on network filesystem that is inaccessible (for
example sshfs or nfs).

How to reproduce the hang:

- mount an sshfs directory
/usr/src/git/bash# sshfs user@host:/ /mnt/test -o cache=no,reconnect

- go to the mounted directory
/usr/src/git/bash# cd /mnt/test

- go back
/mnt/test# cd -

- disconnect the network cable (or shut down the remote host)

- execute some command or script via bash
/usr/src/git/bash# bash -c 'echo Hello World'

- bash hangs, because it tries to execute stat("/mnt/test")

Mikulas


---
 variables.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: bash/variables.c
===================================================================
--- bash.orig/variables.c
+++ bash/variables.c
@@ -899,7 +899,7 @@ set_pwd ()
      don't find OLDPWD in the environment, or it doesn't name a directory,
      make a dummy invisible variable for OLDPWD, and mark it as exported. */
   temp_var = find_variable ("OLDPWD");
-  if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0)
+  if (temp_var == 0 || value_cell (temp_var) == 0)
     {
       temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
       VSETATTR (temp_var, (att_exported | att_invisible));

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Eduardo Bustamante
On Thu, Sep 28, 2017 at 11:44:02AM +0200, Mikulas Patocka wrote:
[...]
> +++ bash/variables.c
> @@ -899,7 +899,7 @@ set_pwd ()
>       don't find OLDPWD in the environment, or it doesn't name a directory,
>       make a dummy invisible variable for OLDPWD, and mark it as exported. */
>    temp_var = find_variable ("OLDPWD");
> -  if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0)
> +  if (temp_var == 0 || value_cell (temp_var) == 0)
>      {
>        temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);

This patch would revert the change introduced in:
  http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=e6f5e0c858b7c0839d346d7d55e56894648c5a33

Which was prompted by the following bug report from John Wiersba:
  https://lists.gnu.org/archive/html/bug-bash/2015-11/msg00115.html

Correct me if I'm wrong, but a hanged sshfs mount will cause many more
issues, not only with OLDPWD.

I tried the following:

dualbus@ubuntu:~/test$ ls -l
total 4
drwxr-xr-x 2 dualbus dualbus 4096 sep 28 10:05 host
dualbus@ubuntu:~/test$ sshfs $host: host
dualbus@ubuntu:~/test$ ls -ld host
drwxr-xr-x 1 dualbus dualbus 20480 sep 28 08:15 host
dualbus@ubuntu:~/test$ cd host
dualbus@ubuntu:~/test/host$ pwd
/home/dualbus/test/host
dualbus@ubuntu:~/test/host$ cd ..
dualbus@ubuntu:~/test$ df host | sed "s/$host/<host>/"
Filesystem     1K-blocks     Used Available Use% Mounted on
<host>:     20511592 13003368   6452528  67% /home/dualbus/test/host
dualbus@ubuntu:~/test$ sudo iptables -A OUTPUT -p tcp -d $host -j DROP
dualbus@ubuntu:~/test$ ls
^C^C^C^C^C

Also tried:

cd ho<TAB> # hangs
cd host # hangs
ls -l host # hangs

So in my opinion, it's not worth to revert this change given that you'll have
many more troubles with a hanged network filesystem.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Chet Ramey
On 9/28/17 11:14 AM, Eduardo A. Bustamante López wrote:

> This patch would revert the change introduced in:
>   http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=e6f5e0c858b7c0839d346d7d55e56894648c5a33
>
> Which was prompted by the following bug report from John Wiersba:
>   https://lists.gnu.org/archive/html/bug-bash/2015-11/msg00115.html
>
> Correct me if I'm wrong, but a hanged sshfs mount will cause many more
> issues, not only with OLDPWD.

This is all correct.  The change was introduced for a reason, and
accommodating a rare occurrence by backing it out would be non-
productive.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

L A Walsh
Chet Ramey wrote:
>
> This is all correct.  The change was introduced for a reason, and
> accommodating a rare occurrence by backing it out would be non-
> productive.
>  
---
The reason?:

Why does bash clear OLDPWD when a child script is started?

OLDPWD is exported and passed to any children, but bash apparently clears
OLDPWD whenever a child script is started...

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

Can bash be fixed to preserve the value of any OLDPWD in its initial
environment, like it does with PWD?
---

I don't see a reason...
I see a "want", but no real reason....

I'd agree it's a rare event to hit though, but when you do...

Requires console access, but changing /etc/profile to
insert a bad OLDPWD to a known down network location might not be
considered a trivial occurrence to someone stressed out and trying to log
in and find out why everyone logging in is hanging...






Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka
In reply to this post by Eduardo Bustamante


On Thu, 28 Sep 2017, Eduardo A. Bustamante López wrote:

> On Thu, Sep 28, 2017 at 11:44:02AM +0200, Mikulas Patocka wrote:
> [...]
> > +++ bash/variables.c
> > @@ -899,7 +899,7 @@ set_pwd ()
> >       don't find OLDPWD in the environment, or it doesn't name a directory,
> >       make a dummy invisible variable for OLDPWD, and mark it as exported. */
> >    temp_var = find_variable ("OLDPWD");
> > -  if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0)
> > +  if (temp_var == 0 || value_cell (temp_var) == 0)
> >      {
> >        temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
>
> This patch would revert the change introduced in:
>   http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=e6f5e0c858b7c0839d346d7d55e56894648c5a33

This patch doesn't revert the above change. It only removes a test if
$OLDPWD is a directory. With this patch, if $OLDPWD points to a directory,
there will be no change, and if $OLDPWD points to non-directory, it will
not be cleared.

> Which was prompted by the following bug report from John Wiersba:
>   https://lists.gnu.org/archive/html/bug-bash/2015-11/msg00115.html
>
> Correct me if I'm wrong, but a hanged sshfs mount will cause many more
> issues, not only with OLDPWD.

Hung mount shouldn't cause problems unless someone is accessing it.

What happened to me - I use the autofs filesystem to automatically mount
filesystems on various machines. I was on some autofs-mounted directory, I
moved to the home directory (which is not on autofs) and I typed startx.
Some times after that I shut down the remote machine that provided the
autofs mount.

The whole X session started to severely mibehave, starting various
programs caused hangs, I couldn't even start an xterm with the shell, I
couldn't even start the chome browser - the reason for the hangs was, that
the OLDPWD variable pointing to the autofs directory ended up being
propagated to the Xserver, to the desktop environment and to any program
that was running within the X session. I caused serious trouble and I
think it should be fixed.

If I started Xwindow on the non-functioning autofs directory, it would be
expected that I get hangs. However, I started Xwindow in the home
directory that has nothing to do with autofs - and I got hangs.

Mikulas


> I tried the following:
>
> dualbus@ubuntu:~/test$ ls -l
> total 4
> drwxr-xr-x 2 dualbus dualbus 4096 sep 28 10:05 host
> dualbus@ubuntu:~/test$ sshfs $host: host
> dualbus@ubuntu:~/test$ ls -ld host
> drwxr-xr-x 1 dualbus dualbus 20480 sep 28 08:15 host
> dualbus@ubuntu:~/test$ cd host
> dualbus@ubuntu:~/test/host$ pwd
> /home/dualbus/test/host
> dualbus@ubuntu:~/test/host$ cd ..
> dualbus@ubuntu:~/test$ df host | sed "s/$host/<host>/"
> Filesystem     1K-blocks     Used Available Use% Mounted on
> <host>:     20511592 13003368   6452528  67% /home/dualbus/test/host
> dualbus@ubuntu:~/test$ sudo iptables -A OUTPUT -p tcp -d $host -j DROP
> dualbus@ubuntu:~/test$ ls
> ^C^C^C^C^C
>
> Also tried:
>
> cd ho<TAB> # hangs
> cd host # hangs
> ls -l host # hangs
>
> So in my opinion, it's not worth to revert this change given that you'll have
> many more troubles with a hanged network filesystem.
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka


On Fri, 29 Sep 2017, Mikulas Patocka wrote:

>
>
> On Thu, 28 Sep 2017, Eduardo A. Bustamante López wrote:
>
> > On Thu, Sep 28, 2017 at 11:44:02AM +0200, Mikulas Patocka wrote:
> > [...]
> > > +++ bash/variables.c
> > > @@ -899,7 +899,7 @@ set_pwd ()
> > >       don't find OLDPWD in the environment, or it doesn't name a directory,
> > >       make a dummy invisible variable for OLDPWD, and mark it as exported. */
> > >    temp_var = find_variable ("OLDPWD");
> > > -  if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0)
> > > +  if (temp_var == 0 || value_cell (temp_var) == 0)
> > >      {
> > >        temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
> >
> > This patch would revert the change introduced in:
> >   http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=e6f5e0c858b7c0839d346d7d55e56894648c5a33
>
> This patch doesn't revert the above change. It only removes a test if
> $OLDPWD is a directory. With this patch, if $OLDPWD points to a directory,
> there will be no change, and if $OLDPWD points to non-directory, it will
> not be cleared.
>
> > Which was prompted by the following bug report from John Wiersba:
> >   https://lists.gnu.org/archive/html/bug-bash/2015-11/msg00115.html
> >
> > Correct me if I'm wrong, but a hanged sshfs mount will cause many more
> > issues, not only with OLDPWD.
>
> Hung mount shouldn't cause problems unless someone is accessing it.
>
> What happened to me - I use the autofs filesystem to automatically mount
> filesystems on various machines. I was on some autofs-mounted directory, I
> moved to the home directory (which is not on autofs) and I typed startx.
> Some times after that I shut down the remote machine that provided the
> autofs mount.
>
> The whole X session started to severely mibehave, starting various
> programs caused hangs, I couldn't even start an xterm with the shell, I
> couldn't even start the chome browser - the reason for the hangs was, that
> the OLDPWD variable pointing to the autofs directory ended up being
> propagated to the Xserver, to the desktop environment and to any program
> that was running within the X session. I caused serious trouble and I
> think it should be fixed.
>
> If I started Xwindow on the non-functioning autofs directory, it would be
> expected that I get hangs. However, I started Xwindow in the home
> directory that has nothing to do with autofs - and I got hangs.
>
> Mikulas

Another problem is that various daemons change the working directory to
"/", so that they don't keep the directory they were started from open -
however they don't clear the $OLDPWD environment variable.

So the $OLDPWD variable in a daemon could contain arbitrary garbage. If
the $OLDPWD variable points to some network directory that is currently
inaccessible, the daemon won't be able to start any bash scripts.

Mikulas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Eduardo Bustamante
In reply to this post by Mikulas Patocka
On Fri, Sep 29, 2017 at 11:12:59AM +0200, Mikulas Patocka wrote:
> This patch doesn't revert the above change. It only removes a test if
> $OLDPWD is a directory. With this patch, if $OLDPWD points to a directory,
> there will be no change, and if $OLDPWD points to non-directory, it will
> not be cleared.

You're right. It doesn't revert it, but it does make it less useful.

> Hung mount shouldn't cause problems unless someone is accessing it.

My reasoning is that if stat()'ing a directory causes everything to
halt, then perhaps fix the source of that problem?

There's no reason why bash should make this a special case.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Eduardo Bustamante
In reply to this post by L A Walsh
On Fri, Sep 29, 2017 at 12:51:37AM -0700, L A Walsh wrote:
[...]
> Why does bash clear OLDPWD when a child script is started?
>
> OLDPWD is exported and passed to any children, but bash apparently clears
> OLDPWD whenever a child script is started...
>
> GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
>
> Can bash be fixed to preserve the value of any OLDPWD in its initial
> environment, like it does with PWD?

Eh, 4.1? That's ~8 years old.

Check the commit I linked, there's the fix you're asking for.

> ---
>
> I don't see a reason...
> I see a "want", but no real reason....
>
> I'd agree it's a rare event to hit though, but when you do...
>
> Requires console access, but changing /etc/profile to
> insert a bad OLDPWD to a known down network location might not be
> considered a trivial occurrence to someone stressed out and trying to log
> in and find out why everyone logging in is hanging...

Why would logins hang? We're talking about OLDPWD here. OLDPWD is not
set if you're not logged in.

The reported scenario is:

- You are in a network filesystem (let's call it /net/myuser)
- chdir() somewhere else, e.g. /home/myuser
  (OLDPWD=/net/myuser, PWD=/home/myuser)
- Then you unplug your computer, or the computer that provides the
  network share.
- Then you start a new bash shell, which will hang because it'll try to
  stat($OLDPWD).

To which the solution is: unmount the network share properly.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

L A Walsh


Eduardo � wrote:

> On Fri, Sep 29, 2017 at 12:51:37AM -0700, L A Walsh wrote:
>  
>> Why does bash clear OLDPWD when a child script is started?
>> OLDPWD is exported and passed to any children, but bash apparently clears
>> OLDPWD whenever a child script is started...
>> GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
>> Can bash be fixed to preserve the value of any OLDPWD in its initial
>> environment, like it does with PWD?
>>    
> Eh, 4.1? That's ~8 years old.
> Check the commit I linked, there's the fix you're asking for.
>  
Check the bug report you linked in your initial response.
I read the report as listed as the 'reason' for the change.  The above was
a quote from the bug report.  Are you saying you saying the
reason given was invalid?
>> Requires console access, but changing /etc/profile to
>> insert a bad OLDPWD to a known down network location might not be
>> considered a trivial occurrence to someone stressed out and trying to log
>> in and find out why everyone logging in is hanging...
>>    
>
> Why would logins hang?
Simple -- OLDPWD is set in /etc/profile to a bad value.  That causes
problems
for everyone logging in, including root.  Granted it is a rare event, and
granted it needs root-console access, but the paragraph described an
annoying situation where someone set the value of OLDPWD in /etc/profile
to a dead-network connection.  Even as someone w/root access tries logging
in to fix the problem, they are hit by the same problem -- which I was
guessing might cause stress -- especially to the one trying to fix it.


> To which the solution is: unmount the network share properly.
>  
Obviously that's the end goal, I was pointing out how annoying it would be
if someone modified /etc/profile to set OLDPWD to a hung-network connection.

I was thinking about the remote possibility of that happening and the
consequent
"annoyed sysadmin" vs. the original bug report you cited being given as
a reason
for not clearing it upon startup.  I'm not heavily for or against it,
but would
lean toward initializing it to a known value, at least, when starting a
login shell.




Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Chet Ramey
In reply to this post by Mikulas Patocka
On 9/29/17 5:12 AM, Mikulas Patocka wrote:

>
>
> On Thu, 28 Sep 2017, Eduardo A. Bustamante López wrote:
>
>> On Thu, Sep 28, 2017 at 11:44:02AM +0200, Mikulas Patocka wrote:
>> [...]
>>> +++ bash/variables.c
>>> @@ -899,7 +899,7 @@ set_pwd ()
>>>       don't find OLDPWD in the environment, or it doesn't name a directory,
>>>       make a dummy invisible variable for OLDPWD, and mark it as exported. */
>>>    temp_var = find_variable ("OLDPWD");
>>> -  if (temp_var == 0 || value_cell (temp_var) == 0 || file_isdir (value_cell (temp_var)) == 0)
>>> +  if (temp_var == 0 || value_cell (temp_var) == 0)
>>>      {
>>>        temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
>>
>> This patch would revert the change introduced in:
>>   http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=e6f5e0c858b7c0839d346d7d55e56894648c5a33
>
> This patch doesn't revert the above change. It only removes a test if
> $OLDPWD is a directory. With this patch, if $OLDPWD points to a directory,
> there will be no change, and if $OLDPWD points to non-directory, it will
> not be cleared.

OLDPWD must be a directory, and while it's technically the user's
responsibility to ensure that it is, the shell should only inherit it
if it has a valid value.  (As I said back in 2015, in the same way it
inherits PWD only if it names the current directory.)

>
>> Which was prompted by the following bug report from John Wiersba:
>>   https://lists.gnu.org/archive/html/bug-bash/2015-11/msg00115.html
>>
>> Correct me if I'm wrong, but a hanged sshfs mount will cause many more
>> issues, not only with OLDPWD.
>
> Hung mount shouldn't cause problems unless someone is accessing it.

That's like saying a problem will only be a problem if someone makes
it a problem.

It really seems like you want bash to save you from a problem you
introduced by yanking a remote mount out from underneath your system.
It seems better to, say, specify that the automount operation is
interruptible than to change the shell for what is a rare occurrence.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka
In reply to this post by Eduardo Bustamante


On Fri, 29 Sep 2017, Eduardo A. Bustamante López wrote:

> On Fri, Sep 29, 2017 at 12:51:37AM -0700, L A Walsh wrote:
> [...]
> > Why does bash clear OLDPWD when a child script is started?
> >
> > OLDPWD is exported and passed to any children, but bash apparently clears
> > OLDPWD whenever a child script is started...
> >
> > GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
> >
> > Can bash be fixed to preserve the value of any OLDPWD in its initial
> > environment, like it does with PWD?
>
> Eh, 4.1? That's ~8 years old.
>
> Check the commit I linked, there's the fix you're asking for.
>
> > ---
> >
> > I don't see a reason...
> > I see a "want", but no real reason....
> >
> > I'd agree it's a rare event to hit though, but when you do...
> >
> > Requires console access, but changing /etc/profile to
> > insert a bad OLDPWD to a known down network location might not be
> > considered a trivial occurrence to someone stressed out and trying to log
> > in and find out why everyone logging in is hanging...
>
> Why would logins hang? We're talking about OLDPWD here. OLDPWD is not
> set if you're not logged in.
>
> The reported scenario is:
>
> - You are in a network filesystem (let's call it /net/myuser)
> - chdir() somewhere else, e.g. /home/myuser
>   (OLDPWD=/net/myuser, PWD=/home/myuser)
> - Then you unplug your computer, or the computer that provides the
>   network share.
> - Then you start a new bash shell, which will hang because it'll try to
>   stat($OLDPWD).
>
> To which the solution is: unmount the network share properly.

Unmounting it doesn't solve it. I unmount /ssh/host/, bash attempts to
execute stat("/ssh/host/directory"), this is intercepted by automounter
and the automounter tries to mount "/ssh/host" again. Automounter spawns
sshfs, sshfs spawns ssh, ssh tries to connect to the host, it times out
after a minute. After a minute, automounter reports an error, the stat()
syscall fails and bash continues.

If this delay happened only occasionally, it would be acceptable. But, if
I start a desktop environment from command line and the $OLDPWD variable
is propagated to every process in the desktop environment, then every bash
script executed in the desktop environment will wait for the automounter
to time out.

If you argue that this is misconfiguration of automounter or sshfs, what
should it do instead? Surely it can't fail immediatelly, it will try to
connect until some timeout - and every bash instance will then wait for
this timeout in the stat syscall.

Here they fixed a similar problem in zsh, because it was poking
directories in its directory history.
https://github.com/grml/grml-etc-core/issues/51

Mikulas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka
In reply to this post by L A Walsh


On Fri, 29 Sep 2017, L A Walsh wrote:

> Chet Ramey wrote:
> >
> > This is all correct.  The change was introduced for a reason, and
> > accommodating a rare occurrence by backing it out would be non-
> > productive.
> >  
> ---
> The reason?:
>
> Why does bash clear OLDPWD when a child script is started?
>
> OLDPWD is exported and passed to any children, but bash apparently clears
> OLDPWD whenever a child script is started...
>
> GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
>
> Can bash be fixed to preserve the value of any OLDPWD in its initial
> environment, like it does with PWD?
> ---
>
> I don't see a reason...
> I see a "want", but no real reason....
>
> I'd agree it's a rare event to hit though, but when you do...
>
> Requires console access, but changing /etc/profile to
> insert a bad OLDPWD to a known down network location might not be
> considered a trivial occurrence to someone stressed out and trying to log
> in and find out why everyone logging in is hanging...

I don't set up OLDPWD in /etc/profile.

I start the desktop environment from console using the "startx" command (I
don't use graphical login screen) and the desktop environment inherits all
variables that were there when I was working with bash on the console -
including $OLDPWD.

A similar problem may happen if you start daemons using scripts in
/etc/init.d/ (i.e. not using systemd) - in this case, the daemon also
inherits all environment variables that were there when the admin was
working with the shell, inclunding $OLDPWD.

Mikulas

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka
In reply to this post by Eduardo Bustamante


On Fri, 29 Sep 2017, Eduardo A. Bustamante López wrote:

> On Fri, Sep 29, 2017 at 11:12:59AM +0200, Mikulas Patocka wrote:
> > This patch doesn't revert the above change. It only removes a test if
> > $OLDPWD is a directory. With this patch, if $OLDPWD points to a directory,
> > there will be no change, and if $OLDPWD points to non-directory, it will
> > not be cleared.
>
> You're right. It doesn't revert it, but it does make it less useful.

Is there some reason why do we need to check if $OLDPWD is a real
directory? dash and ksh accept the $OLDPWD variable, but don't poke it
with the stat syscall. zsh clears $OLDPWD.

I think that if bash did the same thing as dash and ksh, it would be
acceptable.

> > Hung mount shouldn't cause problems unless someone is accessing it.
>
> My reasoning is that if stat()'ing a directory causes everything to
> halt, then perhaps fix the source of that problem?
>
> There's no reason why bash should make this a special case.

The stat syscall doesn't completely halt - it waits until a timeout. But
it is still a problem if every bash script is slowed down by the timeout.

Mikulas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

L A Walsh
In reply to this post by Mikulas Patocka


Mikulas Patocka wrote:
> I don't set up OLDPWD in /etc/profile.
---
    No one does -- unless someone is trying to cause mischief.  It's not
a likely event, but it would be annoying if someone did it.

    But, FWIW, -- it seems like not using 'tainted' values from the
environment in a LOGIN SHELL, would be prudent.

    Is it that difficult to only clear previous OLDPWD and
such when $0 == -bash (or when bash is about to read "/etc/bash_profile")?






Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Mikulas Patocka


On Sat, 30 Sep 2017, L A Walsh wrote:

>
>
> Mikulas Patocka wrote:
> > I don't set up OLDPWD in /etc/profile.
> ---
>    No one does -- unless someone is trying to cause mischief.  It's not
> a likely event, but it would be annoying if someone did it.
>    But, FWIW, -- it seems like not using 'tainted' values from the
> environment in a LOGIN SHELL, would be prudent.
>    Is it that difficult to only clear previous OLDPWD and
> such when $0 == -bash (or when bash is about to read "/etc/bash_profile")?

The problem occurs even in non-login shells - the chrome browser is
started from a bash script, on some distributions firefox is also started
from a bash script, mail daemon may start a script specified in user's
".forward" file. And these scripts also poke $OLDPWD and delay startup.

Mikulas

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix hang if $OLDPWD points to inaccessible directory

Chet Ramey
In reply to this post by Mikulas Patocka
On 9/30/17 4:20 AM, Mikulas Patocka wrote:

> Is there some reason why do we need to check if $OLDPWD is a real
> directory? dash and ksh accept the $OLDPWD variable, but don't poke it
> with the stat syscall. zsh clears $OLDPWD.

It makes no sense to inherit it if it doesn't name a directory (or
"pathname" in the Posix standard), other than the sort of lazy evaluation
that will prevent your particular problem.

This is the same reasoning that rejects inheriting PWD if it doesn't name
the current directory.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|

Bash should reset OLDPWD upon login, *only*.

L A Walsh
In reply to this post by Mikulas Patocka


Mikulas Patocka wrote:
> The problem occurs even in non-login shells -

>  the chrome browser is
> started from a bash script, on some distributions firefox is also started
> from a bash script, mail daemon may start a script specified in user's
> ".forward" file. And these scripts also poke $OLDPWD and delay startup.
>  
---
    It **seemed** to me that the main complaint was when a new shell was
started
and OLDPWD was reset.  I really doubt that people are relying on the
value of
OLDPWD when a browser or deamon is launched. However -- whatever
launches the
background process (chrome or the daemon) SHOULD take responsibility for
setting
the environment correctly for the new process (i.e. bash try to correct
anything
that the launch processes (the ones that launch chrome or the daemon)
are not
correcting.  Only the launching process will know that OLDPWD won't make
a difference for new program.  So in those cases, the launcher should be
fixed --
not bash.

In the case of a user starting a new shell -- OLDPWD has to remain
whatever the
user set it to before they launched a new shell.  If the OLDPWD points to
/hang, the user should clear out OLDPWD before they launch a new shell.

Only in the case of login -- they user CAN'T set it before they login, but
someone **could** have changed the system /etc/profile script to set OLDPWD
to /hang (i.e. someone is behaving "maliciously").  In the case of
login, bash is the first point-of-contact for the user and it should be
started in a "SAFE"
manner.  Suppose you had a file-system that controlled system operations
(like
"/sys or /proc), where reading from a directory or file might influence
the state of the system.  I can show an example of this by doing a
'find' command
through /proc/sys in cygwin on a Win machine (as an admin).  It will cause
my win machine to blue-screen and reboot.

That would be *bad*.

So that's why I say that bash should create a safe-"environment" to log
in with.
If bash doesn't do it, someone could set OLDPWD to whatever file is read
by 'find' that causes the reboot and the person could be locked out of
their system.

Yes it needs console access, so likelihood is small, but consequences
are "troublesome".  So it should be prevented if possible.


>  

Reply | Threaded
Open this post in threaded view
|

Re: Bash should reset OLDPWD upon login, *only*.

Chet Ramey
On 10/1/17 7:30 PM, L A Walsh wrote:

> Only in the case of login -- they user CAN'T set it before they login, but
> someone **could** have changed the system /etc/profile script to set OLDPWD
> to /hang (i.e. someone is behaving "maliciously").

Login shells rarely get OLDPWD from the environment. How about checking
OLDPWD only if it appears in the environment, which would avoid the
set-maliciously-in-etc-profile problem?

That is consistent with the current behavior for importing PWD.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [hidden email]    http://cnswww.cns.cwru.edu/~chet/

Reply | Threaded
Open this post in threaded view
|

Re: Bash should reset OLDPWD upon login, *only*.

L A Walsh


Chet Ramey wrote:

> On 10/1/17 7:30 PM, L A Walsh wrote:
>
>  
>> Only in the case of login -- they user CAN'T set it before they login, but
>> someone **could** have changed the system /etc/profile script to set OLDPWD
>> to /hang (i.e. someone is behaving "maliciously").
>>    
>
> Login shells rarely get OLDPWD from the environment. How about checking
> OLDPWD only if it appears in the environment, which would avoid the
> set-maliciously-in-etc-profile problem?
>
> That is consistent with the current behavior for importing PWD.
>  
That's fine w/me -- I was just concerned about a local DoS, if someone
could "pollute" the login stuff.  The run-time (in a session, not
login) behavior(s) have to be "controlled" by the process that spawned
bash -- I don't see how it could be easily justified to have bash
changing ENV vars unexpectedly in mid-session, when the user has
control via the parent process.

Hmm... there is a bash.bashrc in /etc.... I wonder if that's
a problem.  I wouldn't think it would be as much of a prob, as by
default, I don't think it is called on @ login.  Either way, @ login
or in bashrc-- it's a pretty remote possibility, so unless it could be
made more serious than just a long delay or wait I'm not so sure how
much effort should be invested.  Certainly something to think about
and be ready to change if something worse comes up.

I'll bet the win7-reboot on my cygwin install is limited to my machine
given how it's windows-install is limping (my event-recorder (syslogd)
won't run and MS doesn't know why -- even running an "in-place"
install/upgrade to reset things didn't fix it; only way to likely fix
it is to start with a new system directory & registry which would also
require a reinstall of all SW: Never something to look forward to.








Reply | Threaded
Open this post in threaded view
|

Re: Bash should reset OLDPWD upon login, *only*.

Greg Wooledge
On Mon, Oct 02, 2017 at 05:07:01PM -0700, L A Walsh wrote:
> That's fine w/me -- I was just concerned about a local DoS, if someone
> could "pollute" the login stuff.

You'd have to be root, yes?

> Hmm... there is a bash.bashrc in /etc....

Only if your OS vendor has built bash with that add-on.  It is not part
of the standard bash upstream build, nor is the pathname CONSISTENT
across the various Linux distributions that use it.  (Debian uses
/etc/bash.bashrc and CentOS uses /etc/bashrc and so on.)

In any case, it's under control of the local sysadmin (root).

All this talk of login seems like a red herring to me.  The issue that
was reported is the inheritance of OLDPWD by noninteractive bash scripts
(e.g. wrapper scripts that start web browsers), as well as interactive
shells, which are not typically login shells.  Changing the behavior of
bash when invoked as a login shell (per Subject:) won't do anything to
help the original poster, and I do not understand why it was prposed.

I don't have a solution, but I can list out some options, and people may
consider them, or laugh at them, or whatever.

1) Do nothing.  Leave everything as it is.  The OP solves their issue by
   aliasing startx to "cd / && cd && startx".

2) Have bash clear OLDPWD upon startup, always.

3) Have bash clear OLDPWD upon startup, if invoked as sh.

4) Have bash clear OLDPWD upon startup, if invoked noninteractively.

5) Have bash check whether OLDPWD is a directory only when the OLDPWD
   variable is actually used (either explicitly, or by cd -).

12