#25 /etc/bashrc should not be called for login shells
Opened 3 years ago by tsipa740. Modified 2 years ago

TL;DR:
What i do:
su -s/bin/bash - nobody -c "whoami"
What i expect:
nobody
What i got:

/etc/bashrc: line 100: //.loginouthistory: Permission denied
nobody

https://paste2.org/GXCaDm59


I think this all started from this commit https://pagure.io/setup/c/e3811a969fa4c15cca8594231db296a7c541c8f3
which reasoning i do not understand.

According to bash manual running /etc/bashrc is not supposed to happen in all cases:
https://github.com/bminor/bash/blob/8868edaf2250e09c4e9a1c75ffe3274f28f38581/doc/bash.html#L438

and bash have moderately sophisticated logic in the source code https://github.com/bminor/bash/blob/8868edaf2250e09c4e9a1c75ffe3274f28f38581/shell.c#L1204
which is broken by unconditionally sourcing /etc/bashrc from /etc/profile.

Since i failed to understand reasoning behind the initial commit i cannot say for sure how it supposed to be fixed.


Cannot reproduce:

[root@ci-vm-10-0-139-212 ~]# rpm -q setup
setup-2.13.7-3.fc34.noarch
[root@ci-vm-10-0-139-212 ~]# su -s/bin/bash - nobody -c "whoami"
nobody

Please note that a5d609b changes the logic a lot. But I cannot reproduce the issue without it even.

a5d609b looks correct and should solve the issue, thank you, i overlooked additional condition, just noticed that sourcing is still there in master.

Regarding inability to reproduce this wo a5d609b:
I will take a deeper look tomorrow, in my bashrc there is weird shenanigans around selinuxenabled and $LOGINOUTHISTFILE which i don't see in master.
There is huge chance origin of these things is not rpm, but i cannot check it now.

The important piece i missed:

[root@adsgf ~]# rpm -qa setup
setup-2.12.2-6.el8.noarch

Thanks for looking.

I've checked it with freshly deployed Fedora rawhide without modifications. Closing. Feel free to reopen once you have more data

Metadata Update from @landgraf:
- Issue status updated to: Closed (was: Open)

3 years ago

Hello.

I have confirmed and the original message really is not something from vanilla bashrc, i apologize for a misleading debug.

At the same time i checked a5d609b and i still think it doesn't solve the problem, the bashrc still executed for a login shell called by a su:

[root@zxczcxczx ~]# su -s/bin/bash - nobody -c 'shopt -q login_shell; echo $? ; echo $BASHRCSOURCED'
+ su -s/bin/bash - nobody -c 'shopt -q login_shell; echo $? ; echo $BASHRCSOURCED'
0
Y
++ echo -ne '\033_root@kerneltest002:/root\033\'

and i'm still unable to understand what is the rational behind messing with this logic for bash, bash wants to manage this logic himself explicitly:
https://github.com/bminor/bash/blob/8868edaf2250e09c4e9a1c75ffe3274f28f38581/shell.c#L1210

Metadata Update from @tsipa740:
- Issue status updated to: Open (was: Closed)

3 years ago

bashrc should really only be sourced in interactive session.

# This is the test for interactive session.
[[ $- == *i* ]]

We should put this /etc/profile and /etc/skel/.bashrc

Although I am not one of the crew here, I would like to comment on this issue, that is to provide
information.

About 5 years ago (April 9 2017 ?) /etc/profile was modified (commit 6626f88) by Ondrej Vasik; a
modification that made it into F27 unfortunately.

Unfortunately I say, because the modification was totally unnecessary; moreover it broke
expectations by developers.

The modification: Starting from F27, /etc/bashrc is sourced from /etc/profile at the bottom of
the latter. Once more: a totally unnecessary modification!

The modification was accompanied by comment that clearly showed that the author of
the modification was not aware of the presence of important "infrastructuur"
in ~/.bash_profile and ~/.bashrc. Moreover the comment was wrong.

Why was the modification UNnecessary?

Read the manual page of bash, where it says "INVOCATION"!

  1. a LOGIN shell (either interactive or not) sources ~/.bash_profile after it has sourced
    /etc/profile (in short: "profile" is sourced)
  2. an INTERACTIVE NON-login shell sources ~/.bashrc

Note: if bash is invoked with the -l option (or: --login), then a LOGIN shell is executed.

What catches the eye, is that "bashrc" (/etc/bashrc and ~/.bashrc) is NOT sourced by a LOGIN
shell; HOWEVER, we want an INTERACTIVE login shell to source "bashrc"!

Because of this requirement (read the last line once more!), the already mentioned
infrastructure was introduced in ~/.bash_profile and ~/.bashrc.

As result of this infrastructure, the 4 files are "effectively" sourced in the following
order: (pay attention: EFFECTIVELY!)

  • /etc/profile
  • /etc/bashrc
  • ~/.bashrc at the top of this file, /etc/bashrc is sourced
  • ~/.bash_profile at the top of this file, ~/.bashrc is sourced

Again, because of this "kludge" (infrastructure), the above files are effectively being sourced
in the following order in case of a LOGIN shell:

   /etc/profile, /etc/bashrc, ~/.bashrc and finally: ~/.bash_profile

and in this order in case of an INTERACTIVE NON-login shell:

   /etc/bashrc, ~/.bashrc

The problem that remains to be solved, is to prevent the sourcing of "bashrc" in case of
a NON-interactive LOGIN shell ...
(e.g., a "printf" statement in "bashrc" will make the scp command fail)

A problem that is simply solved by inserting the following statement at the top of ~/.bashrc:
[[ "$-" != *i* ]] && return

What goes into "profile", and what goes into "bashrc" ?

  • output statements can really only be used in "bashrc", as this file is sourced exclusively by
    INTERACTIVE shells.
  • anything that will be "unknown" outside the current environment (i.e. cannot be exported)
    when bash has been invoked as a login shell, must go into "bashrc" in case bash is to be
    invoked again, but now as a NON-login shell.

All further details about the contents of the 4 files, are "religion"-dependent.

When I read Ondrej Vasik's comment in /etc/profile, my thought were as follows:

Ondrej Vasik: bash logins shell run only /etc/profile.
My thought: Indeed, but as result of the infrastructure in ~/.bash_profile and ~/.bashrc, they
do source "bashrc" as well !

Ondrej Vasik: bash non-login shells run only /etc/bashrc.
My thought: WRONG! To begin with, it is ~/.bashrc that is sourced by bash; secondly ONLY
INTERACTIVE NON-login shells source ~/.bashrc ... but yes, and as result of the infrastructure
in ~/.bashrc, they also source /etc/bashrc.

But note, because of the infrastructure ALL INTERACTIVE shells now source "bashrc"! And that
is what we want!

However, it is pertinent that NON-INTERACTIVE login shells are being prevented from
sourcing "bashrc". (simply by inserting [[ "$-" != *i* ]] && return at the top of ~/.bashrc)

Ondrej Vasik: Check for double sourcing is done in /etc/bashrc.
My thought: That requirement results from your modification! (thus, UNnecessary).

Finally, as an example of expectations that are broken by the modification:

As of old, PS1 is changed from its initial value (bash!) in "bashrc"; developers expect the default
value of PS1 at the top of ~/.bashrc. However, because of the modification by Ondrej Vasik, that
is no longer true.

I have written this in the hope that the next one that will modify /etc/profile and/or /etc/bashrc,
will know what is going on in these files.

Henri

Btw, Ondrej Vasik appears to have been forced to this modification because of the following
"feature request" (disguised as a bug report):

https://bugzilla.redhat.com/show_bug.cgi?id=1193590
( Allow bash to have a default profile without the 'rootfiles' package )


Login to comment on this ticket.

Metadata