Skip to content

openrc-user does not work with bash without PAM #1029

Description

@sevmonster

I alluded to this in #1005, and finally found the time to look into it.

Reproducer:

  • OpenRC is built without PAM
  • User has /bin/bash as a shell
  • User sets XDG_RUNTIME_DIR in their ~/.profile
  • The service user.$USER is linked to the user service

Execution steps for starting the service:

  1. user.$USER is started by OpenRC
  2. $RC_LIBEXECDIR/bin/openrc-user $USER is called by the supervisor, with a clean environment
  3. The binary gets $USER's shell, prefixes it with - to start it as a login shell, and executes -/bin/bash -c "$RC_LIBEXECDIR/sh/openrc-user.sh start" as the user
  4. Bash, at this point, does not run any login or other scripts, and directly calls openrc-user.sh start
  5. openrc-user.sh fails, because XDG_RUNTIME_DIR isn't set by any of the previous steps

With PAM/systemd-logind, a PAM session would have been opened by openrc-user, and the session's environment (likely containing XDG_RUNTIME_DIR) would have then been merged with the binary's. Without PAM, or if PAM didn't set XDG_RUNTIME_DIR, it's up to the shell to export the variable. But under Bash, ~/.profile nor any system scripts are ever sourced.

The root of the issue is what I assume is an intentional operation of Bash: Prefixing - to argv[0] does internally cause Bash to think it's a login shell, but because it's being run non-interactively, it does not run any login scripts. This is documented in the Bash manual—in Invoking Bash:

A login shell is one whose first character of argument zero is ‘-’, or one invoked with the --login option.

But then in Bash Startup Files:

Invoked non-interactively

[...]
As noted above, if a non-interactive shell is invoked with the --login option, Bash attempts to read and execute commands from the login shell startup files.

So, the only time login scripts are sourced are when the shell is an interactive login shell, or when it is a non-interactive shell explicitly called with the --login/-l option.

As far as I can tell, the only direct fix for this is to add a shim that prepends --login to the options specifically if the shell is detected as Bash. It should also be able to handle links, since Bash executed as sh will also not execute login scripts without the option:

When invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The --noprofile option inhibits this behavior.

This linking use-case is very common in modern Linux, and I'd say most distros link sh to bash, excluding special kids like Alpine with Busybox ash.

As a Zsh user, this is absurd functionality, so I never expected this to be the issue...

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions