2

I'm writing a special PAM module that is supposed to authenticate user with a password stored in kernel keyring.

The key is added by running the following command as root: keyctl add user some-key 123 @u

It can be accessed and read using keyctl as root without any errors:

[root]# keyctl show @u Keyring 745072288 --alswrv 0 65534 keyring: _uid.0 782818964 --alswrv 0 0 \_ user: some-key [root]# keyctl read 782818964 3 bytes of data in key: 313233 

The following code is the key retrieval part from my custom PAM module:

 key_serial_t key = request_key("user", "some-key", NULL, KEY_SPEC_USER_KEYRING); if (key < 0) { pam_syslog(pamh, LOG_ERR, "Failed to retrieve password from keyring. Error: %d", key); switch (key) { case -ENOMEM: pam_syslog(pamh, LOG_ERR, "request_key failed: Not enough memory"); break; case -EPERM: pam_syslog(pamh, LOG_ERR, "request_key failed: Permission denied"); break; case -ENOKEY: pam_syslog(pamh, LOG_ERR, "request_key failed: No such key"); break; case -EKEYEXPIRED: pam_syslog(pamh, LOG_ERR, "request_key failed: Key expired"); break; case -EKEYREVOKED: pam_syslog(pamh, LOG_ERR, "request_key failed: Key revoked"); break; default: pam_syslog(pamh, LOG_ERR, "request_key failed: Unknown error %d", key); break; } return PAM_AUTH_ERR; } 

The module fails with error -1 (Permission denied). I've verified that the PAM module is indeed running as the root user, so I'm pretty confused at this point.

I've also compiled a separate executable application that retrieves the same key, the same way and it does work when running as root.

Another weird thing I've noticed is that the man page explanation of "EPERM" has nothing to do with permissions:

EPERM The type argument started with a period ('.'). 

And for sure the type string does not contain a period.

Why PAM modules are restricted from accessing keys on root keyring?

1 Answer 1

0

This happens 'cause user session keyring is not linked to the user keyring and can even happen when using cli tool on terminal:

keyctl read <key-uid> keyctl_read_alloc: Permission denied 

You can fix it running:

keyctl link @us @s 

You can also do the same using C API provided by keyutils.h:

 key_serial_t user_session_kr, session_kr; // Get the keyring ID for the user session keyring (@us) user_session_kr = keyctl_get_keyring_ID(KEY_SPEC_USER_SESSION_KEYRING, 0); if (user_session_kr < 0) { pam_syslog(pamh, LOG_ERR, "Failed to get user session keyring ID: %s", strerror(errno)); return -1; } // Get the keyring ID for the session keyring (@s) session_kr = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); if (session_kr < 0) { pam_syslog(pamh, LOG_ERR, "Failed to get session keyring ID: %s", strerror(errno)); return -1; } // Link the user session keyring (@us) to the session keyring (@s) if (keyctl_link(user_session_kr, session_kr) < 0) { pam_syslog(pamh, LOG_ERR, "keyctl_link failed: %s", strerror(errno)); return -1; } 

Adding this code to the start of the PAM module fixes the permission issue I encountered.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.