keyctl(2)
Manipulate the kernel key retention service: read, revoke, time out and link keys and keyrings.
- Since
- Linux 2.6.10check your kernel →
- glibc
- none (use syscall(2))
- System
- Linux
- Man page
- keyctl(2)
Synopsis
#include <linux/keyctl.h> /* Definition of KEY* constants */
#include <sys/syscall.h> /* Definition of SYS_* constants */
#include <unistd.h>
long syscall(SYS_keyctl, int op, ...);Rod's take
Environment variables are where secrets go to die: /proc/PID/environ, core dumps, every child you ever fork. The kernel keyring has been doing this properly since 2.6.10: typed keys, per-key permissions, timeouts the kernel enforces itself, and revocation that doesn't mean killing the process. Process keyring if the secret should die with the process, session keyring if children need it. Set a timeout, read it with keyctl_read_alloc, revoke it when you're done. The API is ugly, the permission bitmask is hostile and the quotas are stingy. Still beats DB_PASSWORD in the environment by a mile.
Flags and arguments that matter
| Name | What it does |
|---|---|
| KEYCTL_READLinux 2.6.10 | Read a key's payload; returns the full payload size so you can detect a short buffer. |
| KEYCTL_REVOKELinux 2.6.10 | Revoke a key; further operations on it fail with EKEYREVOKED. |
| KEYCTL_SET_TIMEOUTLinux 2.6.16 | Expire the key t seconds from now (realtime clock); 0 clears the timeout. |
| KEYCTL_SETPERMLinux 2.6.10 | Set the possessor/user/group/other permission mask on a key. |
| KEYCTL_SEARCHLinux 2.6.10 | Search a keyring tree for a key of a given type and description. |
| KEYCTL_INVALIDATELinux 3.5 | Mark a key invalid immediately and schedule it for garbage collection. |
| KEYCTL_GET_KEYRING_IDLinux 2.6.10 | Resolve a special ID (KEY_SPEC_PROCESS_KEYRING etc.) to a real keyring serial. |
| KEY_SPEC_PROCESS_KEYRING | Process keyring: shared by threads, absent in a fork() child, cleared on execve. |
| KEY_SPEC_SESSION_KEYRING | Session keyring: inherited across fork and preserved across execve. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| ENOKEY | No matching key was found, or an invalid key was specified. |
| EACCES | The requested operation wasn't permitted by the key's permissions. |
| EKEYEXPIRED | An expired key was found or specified. |
| EKEYREVOKED | A revoked key was found or specified. |
| EDQUOT | Creating or linking the key would exceed the caller's key quota. |
Example
#include <keyutils.h> /* -lkeyutils */
key_serial_t key = add_key("user", "myapp:db:password",
pw, pwlen, KEY_SPEC_PROCESS_KEYRING);
if (key == -1) err(1, "add_key");
if (keyctl(KEYCTL_SET_TIMEOUT, key, 600) < 0)
perror("KEYCTL_SET_TIMEOUT");
void *payload = NULL;
long len = keyctl_read_alloc(key, &payload);
if (len < 0) err(1, "keyctl_read_alloc");
connect_db(payload, (size_t)len);
explicit_bzero(payload, (size_t)len);
free(payload);
keyctl(KEYCTL_REVOKE, key);Trimmed from the full walkthrough in The kernel keyring has been in Linux since 2.6.10 and you have never used it.
BSD equivalent
FreeBSD and OpenBSD: no kernel keyring equivalent.
The long version, from the console
Sources
- keyctl(2), man7.org
- KEYCTL_READ(2const), man7.org
- KEYCTL_SET_TIMEOUT(2const), man7.org
- KEYCTL_INVALIDATE(2const), man7.org
- KEYCTL_REVOKE(2const), man7.org
- process-keyring(7), man7.org
- session-keyring(7), man7.org
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
