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?