Home / Alt manpages / pam_selinux(8)

  • pam_selinux(8)
  • Admin command
  • linux

Place pam_selinux Safely in a PAM Session Stack

You will finish with a PAM session configuration that lets pam_selinux set the SELinux context for the next process and restore the earlier context when the session closes. The examples match the installed Linux-PAM package, version 1.5.3-5ubuntu5.7, whose module is at /lib/x86_64-linux-gnu/security/pam_selinux.so.

Allow 15 to 20 minutes. You need root access, a second login path that you have already tested, and an SELinux policy that is appropriate for the service. This module is a session module only. It does not enable SELinux, install policy, or choose a policy for you.

Safety boundary

A malformed PAM file can prevent logins, including administrative logins. Keep an existing root shell or console open while testing. Do not close your last known-good session until the new session has been verified.

1. Check the module and the service file

PAM reads service-specific files from /etc/pam.d/. The filename is the service name, such as login or sshd. Start by checking the module and identifying the service you intend to change:

$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
libpam-modules:amd64 1.5.3-5ubuntu5.7
$ test -r /lib/x86_64-linux-gnu/security/pam_selinux.so && echo 'pam_selinux is installed'
pam_selinux is installed
$ sudo sed -n '1,220p' /etc/pam.d/LOGIN_SERVICE

Replace LOGIN_SERVICE with a real service name, for example login or sshd. The first command is ordinary user work. Reading a root-owned service file may require sudo.

Checkpoint: stop if the module is absent, if you do not have a recovery login, or if you cannot identify which service starts the session you want to label. Installing packages or enabling SELinux is a separate change with its own rollback plan.

2. Understand what open and close do

On session open, the module prepares the execution context used by the next execve call. It also sets the context used for the controlling terminal and for a new kernel keyring. On session close, it restores the contexts that were in effect before the module changed them.

Use both phases for a complete session lifecycle:

session  ...  pam_selinux.so close
session  ...  pam_selinux.so open

The order is not cosmetic. The module documentation recommends placing open after PAM modules that execute applications, and close before those modules. This avoids another module running with an unintended context. On an Ubuntu system with the stock configuration, the SELinux close rule is deliberately near the start of the session stack and the open rule appears later, before the user-session work that follows it.

The module only provides the session type. Do not add it as an auth, account or password rule.

3. Back up the PAM file before editing

This is the one state-changing step in the guide. In the root shell that you will keep open, make a timestamped copy of the exact service file:

$ service=LOGIN_SERVICE
$ sudo cp --preserve=mode,ownership "/etc/pam.d/$service" "/etc/pam.d/$service.before-pam-selinux"
$ sudo ls -l "/etc/pam.d/$service" "/etc/pam.d/$service.before-pam-selinux"

Replace LOGIN_SERVICE before running this. The backup is a recovery file, not a second PAM service file that PAM will load. Keep it until the session test passes.

To undo this guide after a failed edit, restore the backup from the still-open root shell:

$ sudo cp --preserve=mode,ownership "/etc/pam.d/$service.before-pam-selinux" "/etc/pam.d/$service"

Do not delete the backup while you are still testing. Restoring a PAM file is safer than trying to repair several experimental lines from memory.

4. Add the two session rules

Edit only the target service file and preserve its existing control policy. A minimal module entry can use optional, as shown in the installed manual's example:

session  optional  pam_selinux.so close
session  optional  pam_selinux.so open

That example shows module syntax, not a universal placement recommendation. In a real distribution file, copy the surrounding style and place the rules according to the session ordering described above. Existing files may use a bracketed control value so that a machine without a loaded SELinux module can ignore the rule while still treating other failures as errors. Do not replace such a control value with optional without understanding the effect on that service.

If your service already contains pam_selinux.so close and pam_selinux.so open, do not add duplicates. Check the complete file first:

$ sudo grep -n 'pam_selinux\.so' "/etc/pam.d/$service"
12:session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
31:session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open

The line numbers above are illustrative output. Your service may have different numbers and control values. The useful verification is that the intended file contains one deliberate close rule and one deliberate open rule.

5. Choose context input only when you need it

With no extra option, the module uses the default context selected by the SELinux policy. That is the least surprising starting point. The module also supports these mutually exclusive ways to request a role and, when MLS is enabled, a sensitivity level:

  • select_context asks the user interactively for a custom role and MLS level.
  • env_params reads SELINUX_ROLE_REQUESTED and SELINUX_LEVEL_REQUESTED from the PAM environment. If SELINUX_USE_CURRENT_RANGE is set to 1, it also requests the current range.
  • use_current_range uses the current process sensitivity level and suppresses a separate sensitivity request.

Do not put select_context and env_params on the same line. The installed module reports that combination as invalid. Treat environment-controlled role selection as security-sensitive: only use it when the calling service controls that environment and your SELinux policy explicitly supports the requested transition.

6. Verify without locking yourself out

First inspect the final file and the module's presence. Then start a new session through the service you changed while keeping the old session open:

$ sudo grep -n 'pam_selinux\.so' "/etc/pam.d/$service"
$ ls -l /lib/x86_64-linux-gnu/security/pam_selinux.so
$ ssh USERNAME@HOSTNAME

Replace USERNAME and HOSTNAME with a test account and host. The SSH command is only an example. Use the actual service, and use a second terminal or console rather than replacing the shell that can restore the file.

Inside the new session, check the process context if the SELinux tools are installed:

$ id -Z
USER:ROLE:TYPE:LEVEL

The exact context is policy- and machine-specific, so do not expect the placeholder output literally. A successful login alone does not prove the intended domain transition. Compare the result with your policy's expected user context and review the service log if the session fails.

The documented module failures include an invalid or unavailable context, an unknown user, and a session error. A failed open can stop a session depending on the control value. If the test cannot log in, use the still-open recovery shell to restore the backup, then test that the service accepts sessions again before investigating policy.

7. Use debug and verbose only while investigating

Add debug only for a controlled troubleshooting run. It sends module diagnostics through syslog. Add verbose when you need the module to attempt to tell the user that a context was set:

session  ...  pam_selinux.so open debug verbose

These options do not repair an SELinux policy or make an invalid context valid. Remove them after the test, because routine authentication and session logs should not be made noisier than necessary.

Done means

  • The installed module and package version were checked.
  • The target PAM service has one intentional close rule and one intentional open rule.
  • The rules are ordered around other session modules that may execute applications.
  • Any existing bracketed control values were preserved unless their behaviour was deliberately reviewed.
  • A backup remains available, and a new session was tested before the recovery shell was closed.
  • select_context and env_params were not combined, and custom context selection was used only with a matching SELinux policy.