[RFC PATCH 4/4] eppic/keyring: Introduce changes for kernel 4.4
Kamalesh Babulal
kamalesh at linux.vnet.ibm.com
Wed Dec 21 02:05:45 PST 2016
Linux kernel commit 146aa8b1453b ("KEYS: Merge the type-specific data
with the payload data") merges the type-specific data with the payload
data. Introduce these changes to access type/payload data and scrub
the key type.
These changes are not compatible with previous kernel versions,
so add new keyring script file for kernel version >= 4.4 and
kernel version <= 4.8.
Signed-off-by: Kamalesh Babulal <kamalesh at linux.vnet.ibm.com>
Cc: Atsushi Kumagai <ats-kumagai at wm.jp.nec.com>
---
eppic_scripts/keyring_4_4_to_4_8.c | 378 +++++++++++++++++++++++++++++++++++++
1 file changed, 378 insertions(+)
create mode 100644 eppic_scripts/keyring_4_4_to_4_8.c
diff --git a/eppic_scripts/keyring_4_4_to_4_8.c b/eppic_scripts/keyring_4_4_to_4_8.c
new file mode 100644
index 0000000..db74033
--- /dev/null
+++ b/eppic_scripts/keyring_4_4_to_4_8.c
@@ -0,0 +1,378 @@
+string
+skey_opt()
+{
+ return "l";
+}
+
+string
+skey_usage()
+{
+ return "\n";
+}
+
+static void
+skey_showusage()
+{
+ printf("usage : skey %s", skey_usage());
+}
+
+string
+skey_help()
+{
+ return "Help";
+}
+
+#define ASSOC_ARRAY_FAN_OUT 16
+#define ASSOC_ARRAY_FAN_MASK (ASSOC_ARRAY_FAN_OUT - 1)
+#define ASSOC_ARRAY_LEVEL_STEP (ilog2(ASSOC_ARRAY_FAN_OUT))
+#define ASSOC_ARRAY_LEVEL_STEP_MASK (ASSOC_ARRAY_LEVEL_STEP - 1)
+#define ASSOC_ARRAY_KEY_CHUNK_MASK (ASSOC_ARRAY_KEY_CHUNK_SIZE - 1)
+#define ASSOC_ARRAY_KEY_CHUNK_SHIFT (ilog2(BITS_PER_LONG))
+#define ASSOC_ARRAY_PTR_TYPE_MASK 0x1UL
+#define ASSOC_ARRAY_PTR_LEAF_TYPE 0x0UL /* Points to leaf (or nowhere) */
+#define ASSOC_ARRAY_PTR_META_TYPE 0x1UL /* Points to node or shortcut */
+#define ASSOC_ARRAY_PTR_SUBTYPE_MASK 0x2UL
+#define ASSOC_ARRAY_PTR_NODE_SUBTYPE 0x0UL
+#define ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE 0x2UL
+
+/* Keyring stuff */
+#define KEYRING_PTR_SUBTYPE 0x2UL
+
+static int keyring_ptr_is_keyring(const struct assoc_array_ptr *x)
+{
+ return (unsigned long)x & KEYRING_PTR_SUBTYPE;
+}
+
+static int assoc_array_ptr_is_meta(const struct assoc_array_ptr *x)
+{
+ return (unsigned long)x & ASSOC_ARRAY_PTR_TYPE_MASK;
+}
+
+static int assoc_array_ptr_is_leaf(const struct assoc_array_ptr *x)
+{
+ return !assoc_array_ptr_is_meta(x);
+}
+static int assoc_array_ptr_is_shortcut(const struct assoc_array_ptr *x)
+{
+ return (unsigned long)x & ASSOC_ARRAY_PTR_SUBTYPE_MASK;
+}
+static int assoc_array_ptr_is_node(const struct assoc_array_ptr *x)
+{
+ return !assoc_array_ptr_is_shortcut(x);
+}
+
+static void *assoc_array_ptr_to_leaf(const struct assoc_array_ptr *x)
+{
+ return (void *)((unsigned long)x & ~ASSOC_ARRAY_PTR_TYPE_MASK);
+}
+
+static
+unsigned long __assoc_array_ptr_to_meta(const struct assoc_array_ptr *x)
+{
+ return (unsigned long)x &
+ ~(ASSOC_ARRAY_PTR_SUBTYPE_MASK | ASSOC_ARRAY_PTR_TYPE_MASK);
+}
+static
+struct assoc_array_node *assoc_array_ptr_to_node(const struct assoc_array_ptr *x)
+{
+ return (struct assoc_array_node *)__assoc_array_ptr_to_meta(x);
+}
+static
+struct assoc_array_shortcut *assoc_array_ptr_to_shortcut(const struct assoc_array_ptr *x)
+{
+ return (struct assoc_array_shortcut *)__assoc_array_ptr_to_meta(x);
+}
+
+static
+struct assoc_array_ptr *__assoc_array_x_to_ptr(const void *p, unsigned long t)
+{
+ return (struct assoc_array_ptr *)((unsigned long)p | t);
+}
+static
+struct assoc_array_ptr *assoc_array_leaf_to_ptr(const void *p)
+{
+ return __assoc_array_x_to_ptr(p, ASSOC_ARRAY_PTR_LEAF_TYPE);
+}
+static
+struct assoc_array_ptr *assoc_array_node_to_ptr(const struct assoc_array_node *p)
+{
+ return __assoc_array_x_to_ptr(
+ p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_NODE_SUBTYPE);
+}
+
+static
+struct assoc_array_ptr *assoc_array_shortcut_to_ptr(const struct assoc_array_shortcut *p)
+{
+ return __assoc_array_x_to_ptr(
+ p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE);
+}
+
+/* Keyring stuff */
+static inline struct key *keyring_ptr_to_key(const struct assoc_array_ptr *x)
+{
+ void *object = assoc_array_ptr_to_leaf(x);
+ return (struct key *)((unsigned long)object & ~KEYRING_PTR_SUBTYPE);
+}
+
+/* BEGIN: struct key access */
+struct keyring_index_key *get_index_key_from_key(struct key *key)
+{
+ return (struct keyring_index_key *)((unsigned long)&(key->flags)
+ + sizeof(key->flags));
+}
+
+struct key_type *get_type_from_key(struct key *key)
+{
+ return (struct key_type *)((unsigned long)&(key->flags)
+ + sizeof(key->flags));
+}
+
+char *get_description_from_key(struct key *key)
+{
+ return (char *)((unsigned long)&(key->flags)
+ + sizeof(key->flags)
+ + sizeof(struct key_type *));
+}
+
+union key_payload *get_payload_from_key(struct key *key)
+{
+ return (union key_payload *)((unsigned long)&(key->flags)
+ + sizeof(key->flags)
+ + sizeof(struct keyring_index_key));
+}
+
+struct list_head *get_name_link_from_key(struct key *key)
+{
+ return (struct list_head *)((unsigned long)&(key->flags)
+ + sizeof(key->flags)
+ + sizeof(struct keyring_index_key));
+}
+
+struct assoc_array *get_keys_from_key(struct key *key)
+{
+ return (struct assoc_array *)((unsigned long)&(key->flags)
+ + sizeof(key->flags)
+ + sizeof(struct keyring_index_key)
+ + sizeof(struct list_head));
+}
+/* END: struct key access */
+
+static void delete_keyring_subtree(struct assoc_array_ptr *root)
+{
+ struct assoc_array_shortcut *shortcut;
+ struct assoc_array_node *node;
+ struct assoc_array_ptr *cursor, *parent;
+ int slot = -1;
+
+ cursor = root;
+ if (!cursor) {
+ return;
+ }
+
+ if (assoc_array_ptr_is_shortcut(cursor)) {
+ /* Descend through a shortcut */
+ shortcut = assoc_array_ptr_to_shortcut(cursor);
+ parent = cursor;
+ cursor = shortcut->next_node;
+ }
+
+ node = assoc_array_ptr_to_node(cursor);
+ slot = 0;
+
+ if(node->nr_leaves_on_branch <= 0) return;
+
+ do {
+ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
+ struct assoc_array_ptr *ptr = node->slots[slot];
+
+ if (!ptr)
+ continue;
+ if (assoc_array_ptr_is_meta(ptr)) {
+ parent = cursor;
+ cursor = ptr;
+ if (assoc_array_ptr_is_shortcut(cursor)) {
+ /* Descend through a shortcut */
+ shortcut = assoc_array_ptr_to_shortcut(cursor);
+ parent = cursor;
+ cursor = shortcut->next_node;
+ }
+ node = assoc_array_ptr_to_node(cursor);
+ slot = 0;
+ } else {
+ struct key *leaf;
+ struct keyring_index_key *index_key;
+ char *description;
+ void *payload_ptr;
+ int i,j;
+
+ /* no need to delete keyrings, only data */
+ if(keyring_ptr_is_keyring(ptr))
+ continue;
+
+ /* delete the leaf payload */
+ leaf = (struct key *)assoc_array_ptr_to_leaf(ptr);
+ index_key = get_index_key_from_key(leaf);
+ /*
+ Now delete the keys of the different key types.
+ The following key types are handled for now:
+ user, ceph, pkcs7_test, asymmetric(X509), rxpc
+
+ The following key types are NOT handled (yet):
+ dns_resolver (no secret keys, just used for DNS)
+
+ Add a new else if() for new key types.
+ */
+ if(getstr(index_key->type->name) == "user") {
+ struct user_key_payload **user_key_payload;
+ unsigned short datalen;
+
+ payload_ptr=(void *)get_payload_from_key(leaf);
+ user_key_payload = (struct user_key_payload **)payload_ptr;
+ datalen = (*user_key_payload)->datalen;
+ memset((char *)&(*user_key_payload)->data, 'A', datalen);
+ } else if(getstr(index_key->type->name) == "ceph") {
+ struct ceph_crypto_key **ceph_payload;
+ int len;
+
+ payload_ptr=(void *)get_payload_from_key(leaf);
+ ceph_payload = (struct ceph_crypto_key **)payload_ptr;
+ len = (*ceph_payload)->len;
+ memset((char *)&(*ceph_payload)->key, 'A', len);
+ } else if(getstr(index_key->type->name) == "pkcs7_test") {
+ struct user_key_payload **user_key_payload;
+ unsigned short datalen;
+
+ payload_ptr=(void *)get_payload_from_key(leaf);
+ user_key_payload = (struct user_key_payload **)payload_ptr;
+ datalen = (*user_key_payload)->datalen;
+ memset((char *)&(*user_key_payload)->data, 'A', datalen);
+ } else if(getstr(index_key->type->name) == "asymmetric") {
+ struct public_key **public_key;
+ unsigned short keylen;
+
+ /* data[0] is asym_crypto */
+ payload_ptr=(void *)get_payload_from_key(leaf);
+ public_key = (struct public_key **)payload_ptr;
+ keylen = (*public_key)->keylen;
+ memset((char *)&(*public_key)->key, 'A', keylen);
+ } else if(getstr(index_key->type->name) == ".request_key_auth") {
+ struct request_key_auth **request_key;
+ unsigned short datalen;
+
+ payload_ptr=(void *)get_payload_from_key(leaf);
+ request_key = (struct request_key_auth **)payload_ptr;
+ datalen = leaf->datalen;
+ memset((char *)&(*request_key)->data, 'A', datalen);
+ } else if(getstr(index_key->type->name) == "rxrpc") {
+ struct rxrpc_key_token **rxrpc_key_token, *token;
+ struct rxkad_key *kad;
+ struct rxk5_key *k5;
+ int token_count = 0;
+
+ payload_ptr=(void *)get_payload_from_key(leaf);
+ rxrpc_key_token = (struct rxrpc_key_token **)payload_ptr;
+ for(; rxrpc_key_token;
+ rxrpc_key_token = &(*rxrpc_key_token)->next,
+ token_count++) {
+ token = *rxrpc_key_token;
+ switch(token->security_index) {
+ case 2 : /* RXRPC_SECURITY_RXKAD */
+ /* anonymous union, use pointer arithmetic */
+ kad = token->next +
+ sizeof(struct rxrpc_key_token *);
+ memset(&kad.session_key, 'A', 8);
+ memset(&kad.ticket, 'A', kad.ticket_len);
+ break;
+ case 5 : /* RXRPC_SECURITY_RXK5 */
+ /* anonymous union, use pointer arithmetic */
+ k5 = token->next +
+ sizeof(struct rxrpc_key_token *);
+ memset(k5.ticket, 'A', k5.ticket_len);
+ memset(k5.ticket2, 'A', k5.ticket2_len);
+ memset(k5.session.data, 'A', k5.session.data_len);
+ memset(k5->addresses.data, 'A', k5->addresses.data_len);
+ memset(k5->authdata.data, 'A', k5->authdata.data_len);
+ break;
+ default :
+ printf("WARNING: unknown security index: %d\n",
+ token->security_index);
+ }
+ /* max number of tokens = 8 */
+ if(token_count > 8) {
+ printf("WARNING: too many rxrpc tokens!\n");
+ break;
+ }
+ }
+ } else if(getstr(index_key->type->name) == "dns_resolver") {
+ /* nothing to do here, no secret data */
+ } else if(getstr(index_key->type->name) == "big_key") {
+ printf("WARNING: key_type=big_key not handled!\n");
+ } else {
+ printf("WARNING: unsupported key type = %s!\n",
+ getstr(index_key->type->name));
+ }
+ }
+ }
+
+ parent = node->back_pointer;
+ slot = node->parent_slot;
+ if (parent) {
+ /* Move back up to the parent */
+ if (assoc_array_ptr_is_shortcut(parent)) {
+ shortcut = assoc_array_ptr_to_shortcut(parent);
+ cursor = parent;
+ parent = shortcut->back_pointer;
+ slot = shortcut->parent_slot;
+ }
+
+ /* Ascend to next slot in parent node */
+ cursor = parent;
+ node = assoc_array_ptr_to_node(cursor);
+ slot++;
+ }
+ } while(parent);
+
+ return;
+}
+
+void delete_keyring(struct assoc_array *keyring)
+{
+ delete_keyring_subtree(keyring->root);
+}
+
+int
+skey()
+{
+ int i,j,k;
+ struct list_head **tab;
+
+ tab = &keyring_name_hash;
+
+ for (i = 0; i < 32; i++)
+ {
+ struct list_head *next, *head;
+
+ head = (struct list_head *) (tab + i);
+ next = (struct list_head *) head->next;
+
+ if (!next)
+ continue;
+
+ while (next != head)
+ {
+ struct key *mykey, *off = 0;
+ struct list_head *name_link;
+ struct assoc_array *keys;
+
+ mykey = (struct key *)((unsigned long)(next)
+ - (unsigned long)&(off->flags)
+ - sizeof(off->flags)
+ - sizeof(struct keyring_index_key));
+ name_link = get_name_link_from_key(mykey);
+ keys = get_keys_from_key(mykey);
+ delete_keyring(keys);
+ next = (struct list_head *) name_link->next;
+ }
+ }
+ return 1;
+}
--
2.7.4
More information about the kexec
mailing list