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
Task Type Bug Report
Category Packages: Core
Status Closed
Assigned To Sébastien Luttringer (seblu)
David Runge (dvzrv)
Architecture All
Severity Low
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 4
Private No

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
Comment by Vladimir Vrzić (random) - Saturday, 02 February 2013, 20:13 GMT
The other side of the story is that ssh logins are not affected -- sshd (and su, too) PAM config does _not_ check if the user's shell is listed. From the security standpoint, this could be an issue.
Comment by Gaetan Bisson (vesath) - Sunday, 03 February 2013, 08:15 GMT
The default login shell defined in /etc/default/useradd is in /etc/shells but you should assume nothing more: if you run useradd with custom arguments, it is up to you to ensure they are valid by customizing our minimalistic /etc/shells and possibly other configuration files.
Comment by Vladimir Vrzić (random) - Sunday, 03 February 2013, 11:54 GMT
Gaetan, would you care to explain to me, as someone new to Arch, the rationale behind these defaults?

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.
Comment by Gaetan Bisson (vesath) - Sunday, 03 February 2013, 12:13 GMT
Sorry but this bug tracker is not the place for general questions such as these. Please seek help:
- in the forums: https://bbs.archlinux.org/
- or on IRC: https://wiki.archlinux.org/index.php/IRC_Channel
Comment by Steve Ward (planet36) - Thursday, 14 October 2021, 21:58 GMT
man 5 shells says
/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.
Comment by Sébastien Luttringer (seblu) - Monday, 06 December 2021, 23:00 GMT
Sure, but what make you think « full » means « resolved »? Full generally means absolute path as opposed to relative.
Comment by Steve Ward (planet36) - Tuesday, 07 December 2021, 13:48 GMT
That's a good point. I presumed if they meant absolute path, they would've written "absolute" instead of "full".

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".
Comment by Steve Ward (planet36) - Wednesday, 08 December 2021, 13:30 GMT
Regardless of "full" vs "absolute" vs "resolved", these facts remain:
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/
Comment by Sébastien Luttringer (seblu) - Monday, 17 October 2022, 23:12 GMT
David, do you think changing the default shell path in shadow to /usr/bin/bash?
Comment by David Runge (dvzrv) - Tuesday, 18 October 2022, 09:08 GMT
@seblu: As we are a /usr and bin merge [1] distribution I think we should default to /usr/bin/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
Comment by David Runge (dvzrv) - Tuesday, 18 October 2022, 09:50 GMT Comment by nl6720 (nl6720) - Tuesday, 18 October 2022, 10:02 GMT
That ^ could be a dangerous change if neither the filesystem or bash packages are updated to match it.
Comment by David Runge (dvzrv) - Tuesday, 18 October 2022, 10:15 GMT
@nl6720: That's why I'm trying to coordinate it here :)

@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.
Comment by David Runge (dvzrv) - Monday, 24 October 2022, 10:35 GMT
FTR: I have opened upstream tickets with pam, util-linux and shadow to support a vendor location (e.g. /usr/lib/shells.d/) for drop-in files, so that we do not have to rely on /etc/shells in the future.

[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
Comment by Toolybird (Toolybird) - Monday, 24 July 2023, 23:03 GMT
Merging  FS#79184  here (contains details of how our incomplete /etc/shells can break systemd-homed)
Comment by Buggy McBugFace (bugbot) - Tuesday, 08 August 2023, 19:11 GMT
This is an automated comment as this bug is open for more then 2 years. Please reply if you still experience this bug otherwise this issue will be closed after 1 month.
Comment by nl6720 (nl6720) - Friday, 11 August 2023, 07:56 GMT
It's still an issue even now, a decade later.
Comment by loqs (loqs) - Friday, 11 August 2023, 13:21 GMT
@dvzrv your request has been implemented upstream in the three projects you contacted but would require packaging libeconf currently in AUR[1]. Do you think this is the appropriate solution?

[1] https://aur.archlinux.org/packages/libeconf
Comment by David Runge (dvzrv) - Friday, 11 August 2023, 13:33 GMT
Yes, I think so.

I am wondering though whether shadow < 4.14 already has this change.

I can earliest look into this after CCCamp.
Comment by loqs (loqs) - Friday, 11 August 2023, 14:22 GMT
> I am wondering though whether shadow < 4.14 already has this change.
It has not https://github.com/shadow-maint/shadow/commit/a27d5c51f1f34b0c3d965482de400447c072de96
Comment by loqs (loqs) - Monday, 14 August 2023, 18:56 GMT
Currently util-linux is failing to build using meson with libeconf and vendordir enabled [1]:

[1] https://github.com/util-linux/util-linux/issues/2431
Comment by Vladimir Vrzić (random) - Thursday, 17 August 2023, 11:42 GMT
Chiming in on this ticket for the first time after 10+ years (I originally opened it). I'm about to elaborate on a software design issue here, that has already been mentioned in upstream discussions ([1] and [2]), but seems to get overlooked.

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
Comment by loqs (loqs) - Monday, 28 August 2023, 20:58 GMT
I agree with @random the issue should be raised upstream with glibc.
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
Comment by David Runge (dvzrv) - Sunday, 03 September 2023, 14:57 GMT
I have added the /usr/bin locations to the filesystem package for now: https://gitlab.archlinux.org/archlinux/packaging/packages/filesystem/-/commit/db8fce055a018aa7e581ff5901472ca350006d4f
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.
Comment by David Runge (dvzrv) - Monday, 18 September 2023, 11:00 GMT
FTR, the glibc related issue has also been added to a tracking issue with the UAPI group (after speaking to Thorsten Kukuk and others at ASG about this): https://github.com/uapi-group/specifications/issues/76

Loading...