From 3ecf1b4f347210e39b156177e5b8a26ff8d00279 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 22 Aug 2011 14:08:43 +0100 Subject: [PATCH] KEYS: keyctl_get_keyring_ID() should create a session keyring if create flag set The keyctl call: keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1) should create a session keyring if the process doesn't have one of its own because the create flag argument is set - rather than subscribing to and returning the user-session keyring as: keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0) will do. This can be tested by commenting out pam_keyinit in the /etc/pam.d files and running the following program a couple of times in a row: #include #include #include int main(int argc, char *argv[]) { key_serial_t uk, usk, sk, nsk; uk = keyctl_get_keyring_ID(KEY_SPEC_USER_KEYRING, 0); usk = keyctl_get_keyring_ID(KEY_SPEC_USER_SESSION_KEYRING, 0); sk = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); nsk = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1); printf("keys: %08x %08x %08x %08x\n", uk, usk, sk, nsk); return 0; } Without this patch, I see: keys: 3975ddc7 119c0c66 119c0c66 119c0c66 keys: 3975ddc7 119c0c66 119c0c66 119c0c66 With this patch, I see: keys: 2cb4997b 34112878 34112878 17db2ce3 keys: 2cb4997b 34112878 34112878 39f3c73e As can be seen, the session keyring starts off the same as the user-session keyring each time, but with the patch a new session keyring is created when the create flag is set. Reported-by: Greg Wettstein Signed-off-by: David Howells Tested-by: Greg Wettstein Signed-off-by: James Morris --- security/keys/process_keys.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 3bc6071ad633..1068cb1939b3 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -589,12 +589,22 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ret = install_user_keyrings(); if (ret < 0) goto error; - ret = install_session_keyring( - cred->user->session_keyring); + if (lflags & KEY_LOOKUP_CREATE) + ret = join_session_keyring(NULL); + else + ret = install_session_keyring( + cred->user->session_keyring); if (ret < 0) goto error; goto reget_creds; + } else if (cred->tgcred->session_keyring == + cred->user->session_keyring && + lflags & KEY_LOOKUP_CREATE) { + ret = join_session_keyring(NULL); + if (ret < 0) + goto error; + goto reget_creds; } rcu_read_lock();