set bash env variables before running scripts

Message ID 20220312225813.206988-1-andrew.gregory.8@gmail.com
State New
Headers show
Series set bash env variables before running scripts | expand

Commit Message

Andrew Gregory March 12, 2022, 10:58 p.m. UTC
Bash sources user configuration files under a number of conditions that
can cause issues with scripts when bash is used as the scriptlet shell.

Bash assumes it's being run under rsh/ssh if stdin is connected to a
socket and sources the user bashrc unless the environment variable
$SHLVL is >= 2.  Commit 6a4c6a02de9b45abe4c0f78c4f5d14d92d3359d6
switched from pipes to sockets when communicating with child processes
to work around SIGPIPE issues.  Normally $SHLVL would be inherited from
the shell running pacman, but operations involving scriptlets are
generally run with sudo which does not let the $SHLVL variable through
unless specifically configured to.

Similarly $BASH_ENV can cause bash to source user-specified configuration
files if set.

https://lists.gnu.org/archive/html/help-bash/2022-02/msg00082.html

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
---

Not entirely sure we should actually be unsetting $BASH_ENV, but Chet
recommended it.

 lib/libalpm/util.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Allan McRae March 13, 2022, 12:45 a.m. UTC | #1
On 13/3/22 08:58, Andrew Gregory wrote:
> Bash sources user configuration files under a number of conditions that
> can cause issues with scripts when bash is used as the scriptlet shell.
> 
> Bash assumes it's being run under rsh/ssh if stdin is connected to a
> socket and sources the user bashrc unless the environment variable
> $SHLVL is >= 2.  Commit 6a4c6a02de9b45abe4c0f78c4f5d14d92d3359d6
> switched from pipes to sockets when communicating with child processes
> to work around SIGPIPE issues.  Normally $SHLVL would be inherited from
> the shell running pacman, but operations involving scriptlets are
> generally run with sudo which does not let the $SHLVL variable through
> unless specifically configured to.
> 
> Similarly $BASH_ENV can cause bash to source user-specified configuration
> files if set.
> 
> https://lists.gnu.org/archive/html/help-bash/2022-02/msg00082.html
> 
> Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
> ---
> 
> Not entirely sure we should actually be unsetting $BASH_ENV, but Chet
> recommended it.
> 
>   lib/libalpm/util.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
> index 06e0fe7f2..7340ce832 100644
> --- a/lib/libalpm/util.c
> +++ b/lib/libalpm/util.c
> @@ -659,6 +659,11 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[],
>   					"/", strerror(errno));
>   			exit(1);
>   		}
> +		/* bash thinks it's being run under rsh/ssh if stdin is a socket and
> +		 * sources ~/.bashrc unles SHLVL is > 1 */

Typo

> +		setenv("SHLVL", "1", 0);

 From reading everything, I expected this to be >=2.  I'm entirely lost 
why it is set to 1!

> +		/* bash sources $BASH_ENV when run non-interactively */
> +		unsetenv("BASH_ENV");
>   		umask(0022);
>   		_alpm_reset_signals();
>   		execv(cmd, argv);
Andrew Gregory March 14, 2022, 5:23 a.m. UTC | #2
(accidentally moved off-list, moving back to pacman-dev)

On 03/13/22 at 10:56am, Allan McRae wrote:
> On 13/3/22 10:46, Andrew Gregory wrote:
> > Bash increments it when it starts, so it'll be 2 in the scriptlet process.
> 
> Can you just set it to 2?  Saves me needing such knowledge!  Or is there a
> side effect I am missing?

No other side effects that I'm aware of.  Might just tweak the comment though.

Patch

diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 06e0fe7f2..7340ce832 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -659,6 +659,11 @@  int _alpm_run_chroot(alpm_handle_t *handle, const char *cmd, char *const argv[],
 					"/", strerror(errno));
 			exit(1);
 		}
+		/* bash thinks it's being run under rsh/ssh if stdin is a socket and
+		 * sources ~/.bashrc unles SHLVL is > 1 */
+		setenv("SHLVL", "1", 0);
+		/* bash sources $BASH_ENV when run non-interactively */
+		unsetenv("BASH_ENV");
 		umask(0022);
 		_alpm_reset_signals();
 		execv(cmd, argv);