FS#33677 - [filesystem][shadow] /usr/bin/bash not listed as an allowed user shell in /etc/shells
Attached to Project:
Arch Linux
Opened by Vladimir Vrzić (random) - Saturday, 02 February 2013, 16:53 GMT
Last edited by David Runge (dvzrv) - Monday, 18 September 2023, 13:50 GMT
Opened by Vladimir Vrzić (random) - Saturday, 02 February 2013, 16:53 GMT
Last edited by David Runge (dvzrv) - Monday, 18 September 2023, 13:50 GMT
|
Details
Description:
bash is by default installed as /usr/bin/bash, with a symlink in /bin, but /usr/bin/bash is not listed as a valid user shell in /etc/shells by default. Since /usr/bin is before /bin in the default PATH, if one adds a user with a command like # useradd [...] -s $(which bash) myuser this user will be unable to login from system console (or via any PAM path that uses pam_shells.so) Additional info: /etc/shells from filesystem 2013.01-3 Steps to reproduce: Create a new user with a shell of /usr/bin/bash: useradd -m -g users -s /usr/bin/bash testuser or useradd -m -g users -s $(which bash) testuser and try to login on tty1. |
This task depends upon
Closed by David Runge (dvzrv)
Monday, 18 September 2023, 13:50 GMT
Reason for closing: Fixed
Additional comments about closing: Fixed with filesystem 2023.09.18-1
Monday, 18 September 2023, 13:50 GMT
Reason for closing: Fixed
Additional comments about closing: Fixed with filesystem 2023.09.18-1
Concretely, why is bash installed as /usr/bin/bash and then symlinked from /bin, while zsh exists only as /bin/zsh?
Second, why is some of the default /etc/pam.d/* configuration structured, but most is not? For example, what's the purpose of a config file named /etc/pam.d/system-remote-login in the base install? sshd config does not include it -- actually, no PAM config file in the base includes it.
- in the forums: https://bbs.archlinux.org/
- or on IRC: https://wiki.archlinux.org/index.php/IRC_Channel
/etc/shells is a text file which contains the full pathnames of valid login shells.
If "full pathname" means the resolved absolute path, then /usr/bin/bash should be in /etc/shells.
I couldn't find a definition for "full pathname", but from reading the man page for bash, it seems like "full pathname" is synonymous with "absolute pathname".
1) /bin is not in the default $PATH of the current official Arch ISO image (2021.12.01)
2) /usr/bin/bash is _the_ default full pathname of bash in Arch. [0]
[0] https://archlinux.org/packages/core/x86_64/bash/
I can adapt that file and look at whether we can also apply a patch there instead of relying on an outdated custom file.
On a related note: The zsh package is adding zsh to /etc/shells using its .install file [2]. For conformity, shouldn't bash do the same? Or do we *need* the sh and bash entries to already be in there?
[1] https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/
[2] https://github.com/archlinux/svntogit-packages/blob/be21e4cdefb82888a16acf13f6c5636d9d2032f4/trunk/zsh.install
@seblu: As mentioned in https://bugs.archlinux.org/task/68741, let's get the /etc/sub{g,u}id change out the door first. In case I need to make further adjustments to the shadow package before we can release filesystem/shadow, I'll revert the SHELL change for /etc/default/useradd.
[1] https://github.com/linux-pam/linux-pam/issues/498
[2] https://github.com/util-linux/util-linux/issues/1857
[3] https://github.com/shadow-maint/shadow/issues/587
FS#79184here (contains details of how our incomplete /etc/shells can break systemd-homed)[1] https://aur.archlinux.org/packages/libeconf
I am wondering though whether shadow < 4.14 already has this change.
I can earliest look into this after CCCamp.
It has not https://github.com/shadow-maint/shadow/commit/a27d5c51f1f34b0c3d965482de400447c072de96
[1] https://github.com/util-linux/util-linux/issues/2431
Linux has an API, in the standard C library, for iterating over valid login shells in /etc/shells, that looks like this:
setusershell() rewinds the iterator
getusershell() gets the next line, opening the file if necessary
endusershell() closes the file
In practice, it is very easy for applications to use this API, without having to deal with, or even know about, /etc/shells directly. For example, if we just want to print valid login shells:
print_shells() {
char *shell;
while (shell = getusershell()) {
printf("%s\n", shell);
}
endusershell();
free(shell);
}
This is the de facto default interface that deals with valid login shells. The fact that glibc exposes it when _DEFAULT_SOURCE is defined indicates that application programs can expect this API to be available by default.
This API originated in 4.3BSD, and is present in all BSD variants, as well as macOS, alternative Linux C libraries like musl, and other Unix variants (HP-UX, for example).
From the clean software design perspective, if a Linux distribution wants to modify this functionality and pull valid shells from other files in addition to /etc/shells, this would be most elegantly accomplished by modifying the default API in the C library shipped by the distribution.
Changing the C library implementation means that application programs like chsh, su and pam_shells.so do not need to know anything about the new files (e.g. /usr/lib/shells.d): as long as they use the default API, they will be able to iterate through available login shells. Such an approach keeps their implementation simple, while keeping the system behavior consistent, without need to duplicate any code. This is in line with the Unix software design philosophy[3].
Having a solution where the default API is ignored, and all applications are separately patched with the new behavior is not good software design, as it would lead to:
a) an inconsistent system, as behavior exposed to the programmers through the API would differ from the behavior exposed to package maintainers through the file system layout,
b) duplication of code, as every application that needs to iterate through available login shells would need to include its own implementation,
c) difficulties in changing the implementation. If in the future we would endeavor to change the implementation, by for example, including /usr/local/lib/shells.d in the searchable paths, we would need to patch each an every application, because the behavior is duplicated, with the added risk of more inconsistencies appearing in the future, as the separate implementations diverge.
From a pragmatic's standpoint, it would be easiest to add paths (including symlinks) to all shells supported by the system to /etc/shells and get a working system.
But if the desire is to improve the system by allowing independent packagers (e.g. AUR) to easily enable new login shells, while still having a consistently designed system, the only clean way is to change the behavior behind the API in the C library, and have all application use that as the single source of truth.
[1] https://github.com/linux-pam/linux-pam/issues/498#issuecomment-1288457808
[2] https://github.com/util-linux/util-linux/pull/1933#issuecomment-1331792433
[3] https://en.wikipedia.org/wiki/Unix_philosophy#Eric_Raymond's_17_Unix_Rules
There are also projects directly using /etc/shells [1] as well as those using getusershell [2][3].
There are also shortcomings in the current implementations such as the build failure with meson, `chsh -l` still using getusershell even when util-linux is built with vendordir and libeconf so it is no longer possible to list shells that are considered valid, shadow moves /etc/security/ to $vendordir/security/ when built with vendordir and libeconf.
There is also the issue that anything that creates /etc/shells after the move will override the use of $vedordir/shells and potentially result in the user being locked out.
Given the above I would suggest differing switching to vendordir and libeconf and implement a fix similar to that used in
FS#73911. Have the post_upgrade function of bash.install add /usr/bin/bash to /etc/shells.[1] https://gitlab.gnome.org/GNOME/gnome-terminal/-/blob/3.48.2/src/terminal-util.cc?ref_type=tags#L711
[2] https://github.com/SSSD/sssd/blob/2.9.1/src/responder/common/responder_common.c#L1239
[3] https://github.com/fairyglade/ly/blob/v0.6.0/src/login.c#L572
Also I have added both /bin and /usr/bin locations for bash and sh to the bash package: https://gitlab.archlinux.org/archlinux/packaging/packages/bash/-/commit/20244daa4cca1e08f0d01db1bf68908176a5aa7e
@loqs: Thanks for looking investigating the issues here. I agree that upstream glibc needs to be contacted over this and a more unifying fix should be applied there.