krb5 commit [krb5-1.12]: Work around Linux session keyring write behavior
Tom Yu
tlyu at MIT.EDU
Mon Jan 13 15:16:12 EST 2014
https://github.com/krb5/krb5/commit/dd9975a4345447f3e764472c4d14fb56fdeeece5
commit dd9975a4345447f3e764472c4d14fb56fdeeece5
Author: Greg Hudson <ghudson at mit.edu>
Date: Thu Jan 9 00:18:44 2014 -0500
Work around Linux session keyring write behavior
If the session keyring matches the user session keyring, write
explicitly to the user session keyring. Otherwise the kernel might
create a new session keyring for the process, making the resulting
cache collection invisible to other processes.
(cherry picked from commit 0642afa544b00054048775d0b9796923bf018e22)
ticket: 7814
version_fixed: 1.12.1
status: resolved
src/lib/krb5/ccache/cc_keyring.c | 28 ++++++++++++++++++++++++----
1 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
index a02cdf0..a0c8035 100644
--- a/src/lib/krb5/ccache/cc_keyring.c
+++ b/src/lib/krb5/ccache/cc_keyring.c
@@ -459,6 +459,26 @@ get_persistent_real(uid_t uid)
#endif
/*
+ * If a process has no explicitly set session keyring, KEY_SPEC_SESSION_KEYRING
+ * will resolve to the user session keyring for ID lookup and reading, but in
+ * some kernel versions, writing to that special keyring will instead create a
+ * new empty session keyring for the process. We do not want that; the keys we
+ * create would be invisible to other processes. We can work around that
+ * behavior by explicitly writing to the user session keyring when it matches
+ * the session keyring. This function returns the keyring we should write to
+ * for the session anchor.
+ */
+static key_serial_t
+session_write_anchor()
+{
+ key_serial_t s, u;
+
+ s = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
+ u = keyctl_get_keyring_ID(KEY_SPEC_USER_SESSION_KEYRING, 0);
+ return (s == u) ? KEY_SPEC_USER_SESSION_KEYRING : KEY_SPEC_SESSION_KEYRING;
+}
+
+/*
* Find or create a keyring within parent with the given name. If possess is
* nonzero, also make sure the key is linked from possess. This is necessary
* to ensure that we have possession rights on the key when the parent is the
@@ -644,14 +664,14 @@ get_collection(const char *anchor_name, const char *collection_name,
} else if (strcmp(anchor_name, KRCC_THREAD_ANCHOR) == 0) {
anchor_id = KEY_SPEC_THREAD_KEYRING;
} else if (strcmp(anchor_name, KRCC_SESSION_ANCHOR) == 0) {
- anchor_id = KEY_SPEC_SESSION_KEYRING;
+ anchor_id = session_write_anchor();
} else if (strcmp(anchor_name, KRCC_USER_ANCHOR) == 0) {
/* The user keyring does not confer possession, so we need to link the
* collection to the process keyring to maintain possession rights. */
anchor_id = KEY_SPEC_USER_KEYRING;
possess_id = KEY_SPEC_PROCESS_KEYRING;
} else if (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0) {
- anchor_id = KEY_SPEC_SESSION_KEYRING;
+ anchor_id = session_write_anchor();
} else {
return KRB5_KCC_INVALID_ANCHOR;
}
@@ -926,7 +946,7 @@ krb5_krcc_initialize(krb5_context context, krb5_ccache id,
/* If this is the legacy cache in a legacy session collection, link it
* directly to the session keyring so that old code can see it. */
if (is_legacy_cache_name(data->name))
- (void)keyctl_link(data->cache_id, KEY_SPEC_SESSION_KEYRING);
+ (void)keyctl_link(data->cache_id, session_write_anchor());
kret = krb5_krcc_save_principal(context, id, princ);
@@ -1041,7 +1061,7 @@ krb5_krcc_destroy(krb5_context context, krb5_ccache id)
}
/* If this is a legacy cache, unlink it from the session anchor. */
if (is_legacy_cache_name(d->name))
- (void)keyctl_unlink(d->cache_id, KEY_SPEC_SESSION_KEYRING);
+ (void)keyctl_unlink(d->cache_id, session_write_anchor());
}
k5_cc_mutex_unlock(context, &d->lock);
More information about the cvs-krb5
mailing list