FS#47884 - [filesystem] /etc/profile should check whether PATH is empty before overwriting it
Attached to Project:
Arch Linux
Opened by Murukesh Mohanan (murukesh) - Monday, 25 January 2016, 03:11 GMT
Last edited by Sébastien Luttringer (seblu) - Sunday, 10 December 2017, 16:06 GMT
Opened by Murukesh Mohanan (murukesh) - Monday, 25 January 2016, 03:11 GMT
Last edited by Sébastien Luttringer (seblu) - Sunday, 10 December 2017, 16:06 GMT
|
Details
Description:
/etc/profile contains the following lines: # Set our default path PATH="/usr/local/sbin:/usr/local/bin:/usr/bin" export PATH For anyone using pam_env (i.e., /etc/environment and ~/.pam_environment) to manage their PATH, this is horrendous. You should at least check if PATH is empty before overwriting it willy nilly. Additional info: * package version(s): filesystem 2015.09-1 * config and/or log files etc.: /etc/profile Steps to reproduce: Enable pam_env in PAM configuration (which it is by default in /etc/pam.d/system-login). Set in /etc/environment: PATH=/usr/local/sbin:/usr/local/bin:/usr/bin and in ~/.pam_environment: FOO=/some/dir PATH DEFAULT=${PATH}:${FOO}/bin Re-login (or SSH to localhost, or login in another TTY ...). Run `echo $PATH` in a terminal. Expected: /usr/local/sbin:/usr/local/bin:/usr/bin:/some/dir/bin Instead, I get: /usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl (The latter paths are not relevant to this bug.) Worse yet, if you do use .pam_environment in the manner shown (appending to $PATH) without setting a full value before doing so, PATH is set to just :/some/dir/bin, which just opens up a security hole. In practice, this messes up SSh-based commands like ssh-copy-id or scp, which fail with very mysterious errors (laptop being the Arch system): ~ scp foo laptop: zsh:1: command not found: scp lost connection The reason no one noticed this might be because SSH has a default PATH. According to /etc/ssh/sshd_config: # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin And that's what I get when I SSH after commenting out all mentions of PATH in /etc/environment and ~/.pam_environment. So by default, even though /etc/profile isn't sourced for non-login shells, I still get a PATH of /usr/bin:/bin:/usr/sbin:/sbin when I run ssh host some-command. At least the following would be good: if [ -z "$PATH" ]; then # Set our default path PATH="/usr/local/sbin:/usr/local/bin:/usr/bin" export PATH fi Ideally, the default PATH should be set in /etc/environment. I'm using zsh if it matters, and I don't use or care about zshenv. |
This task depends upon
Closed by Sébastien Luttringer (seblu)
Sunday, 10 December 2017, 16:06 GMT
Reason for closing: Implemented
Additional comments about closing: filesystem 2017.10-2
Sunday, 10 December 2017, 16:06 GMT
Reason for closing: Implemented
Additional comments about closing: filesystem 2017.10-2
That was the simplest test I could think of, but there could be other tests. Doesn't change my point that pam_env, which is explicitly meant for managing environment variables, should not be overridden by the *default* /etc/profile. The default setup does use pam_env, so it should leave environment variables to pam_env.
Another way could be to test if the given directories are already in PATH:
http://unix.stackexchange.com/a/4973/70524
http://unix.stackexchange.com/a/124447/70524
I don't know how you're missing it, but there are situations where .profile doesn't cut it. SSH is, again, the most obvious case. Unless you let SSH start an interactive shell, neither .profile nor /etc/profile is sourced.
So, if I have /some/path/bin, and I want it in my PATH, and I want it in my PATH no matter what so that I can run ssh laptop foo where foo is /some/path/foo, pam_env is the simplest option.
Yes, pam_env has deficiencies, most notably the absence of $HOME. People have worked around that [1], but if this change won't happen, that is pretty much beyond hope.
Unless you want me to go down the zshenv road, which is very shell-specific, and has led to enough complaints here already.
[1]: https://fedorahosted.org/linux-pam/ticket/24
> I really don't want start a "but $OTHER_DISTRO does X" discussion.
Discussing what other distros do would, in fact, provide useful data points.
FOO=/some/dir
PATH DEFAULT=${PATH}:${FOO}/bin
Note the DEFAULT=. That's what triggers expansion of variables (named using ${...}). I can do it as many times as I need:
PATH DEFAULT=${PATH}:/some/other/dir
PATH DEFAULT=${PATH}:/a/third/dir
Say you have these four lines in .pam_environment, but no initial value is set for PATH, and if you do: ssh localhost /usr/bin/env, you'll see:
PATH=:/some/dir/bin:/some/other/dir:/a/third/dir
As I said, ideally the PATH would be defined in /etc/environment. Then, I can append to it as I need, and that can be done in .pam_environment or .profile as needed. The problem with the current defaults is that any changes I do make to the PATH in .pam_environment are lost when /etc/profile gets sourced.
As for other distros:
1. Ubuntu uses /etc/environment. It works without problems. [1]
2. Debian uses /etc/profile, but there was a bug [2] filed long, *long* ago about using /etc/environment, without much activity. I'll need to poke it.
3. Fedora uses a function to add paths to PATH, like in one of the links I suggested in my first comment. The relevant bits in /etc/profile [3]:
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}
...
# Path manipulation
if [ "$EUID" = "0" ]; then
pathmunge /usr/sbin
pathmunge /usr/local/sbin
else
pathmunge /usr/local/sbin after
pathmunge /usr/sbin after
fi
...
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
...
unset -f pathmunge
However, apparently Fedora doesn't use pam_env otherwise, and I don't know where the default PATH is set. It isn't in /etc/environment on a live system. It is nice of them to not overwrite PATH, though.
[1]: http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/wily/pam/wily/view/head:/debian/libpam-modules.postinst#L23
[2]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=65611
[3]: https://git.fedorahosted.org/cgit/setup.git/tree/profile#n11
I finally looked into this BR and I implemented something like fedora does in our profile.
It should be fairly simple and arguably more cohesive to port the parts of profile.d that set PATH to /usr/lib/environment.d/*.conf files. Then users could bypass the pam_environment/profile.d mess altogether by adding files in ~/.config/systemd/environment.d .
Will look environment.d later, but that sound promising.
Here is a patch proposing to change the order of SDDM as a stop-gap measure, but perhaps it should be extended to respect the previous PATH?
https://github.com/sddm/sddm/pull/922
EDIT: Sorry, misunderstood the comment.
FS#55482with a different cause:@falconindy,
The current version of filesystem incorrectly orders /usr/bin before /usr/local/bin
I've determined that this is caused by /etc/login.defs which is part of the shadow package... perhaps it should set ENV_SUPATH and ENV_PATH to /usr/local/sbin:/usr/local/bin:/usr/bin which is the Arch defaults. Currently /etc/profile starts off with PATH initialized to /usr/bin and skips over that directory while appending all the rest.
@seblu,
I think appendpath should not be unset until after /etc/profile.d/*.sh is sourced, then other profiles can take advantage of this. e.g. perlbin.sh
Also, the systemd generator may be working for nspawn containers, but it does nothing for the host system, see above.
Is this how systemd is supposed to work?