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 <[email protected]>
Cc: Atsushi Kumagai <[email protected]>
---
 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


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to