aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/keys.txt18
-rw-r--r--include/keys/user-type.h1
-rw-r--r--include/linux/key.h8
-rw-r--r--security/keys/key.c56
-rw-r--r--security/keys/keyring.c64
-rw-r--r--security/keys/user_defined.c33
6 files changed, 3 insertions, 177 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 31154882000a..6304db59bfe4 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -860,24 +860,6 @@ The structure has a number of fields, some of which are mandatory:
860 It is safe to sleep in this method. 860 It is safe to sleep in this method.
861 861
862 862
863 (*) int (*duplicate)(struct key *key, const struct key *source);
864
865 If this type of key can be duplicated, then this method should be
866 provided. It is called to copy the payload attached to the source into the
867 new key. The data length on the new key will have been updated and the
868 quota adjusted already.
869
870 This method will be called with the source key's semaphore read-locked to
871 prevent its payload from being changed, thus RCU constraints need not be
872 applied to the source key.
873
874 This method does not have to lock the destination key in order to attach a
875 payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
876 prevents anything else from gaining access to the key.
877
878 It is safe to sleep in this method.
879
880
881 (*) int (*update)(struct key *key, const void *data, size_t datalen); 863 (*) int (*update)(struct key *key, const void *data, size_t datalen);
882 864
883 If this type of key can be updated, then this method should be provided. 865 If this type of key can be updated, then this method should be provided.
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index 26f6ec38577a..a3dae1803f45 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -35,7 +35,6 @@ struct user_key_payload {
35extern struct key_type key_type_user; 35extern struct key_type key_type_user;
36 36
37extern int user_instantiate(struct key *key, const void *data, size_t datalen); 37extern int user_instantiate(struct key *key, const void *data, size_t datalen);
38extern int user_duplicate(struct key *key, const struct key *source);
39extern int user_update(struct key *key, const void *data, size_t datalen); 38extern int user_update(struct key *key, const void *data, size_t datalen);
40extern int user_match(const struct key *key, const void *criterion); 39extern int user_match(const struct key *key, const void *criterion);
41extern void user_destroy(struct key *key); 40extern void user_destroy(struct key *key);
diff --git a/include/linux/key.h b/include/linux/key.h
index 53513a3be53b..4d189e51bc6c 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -193,14 +193,6 @@ struct key_type {
193 */ 193 */
194 int (*instantiate)(struct key *key, const void *data, size_t datalen); 194 int (*instantiate)(struct key *key, const void *data, size_t datalen);
195 195
196 /* duplicate a key of this type (optional)
197 * - the source key will be locked against change
198 * - the new description will be attached
199 * - the quota will have been adjusted automatically from
200 * source->quotalen
201 */
202 int (*duplicate)(struct key *key, const struct key *source);
203
204 /* update a key of this type (optional) 196 /* update a key of this type (optional)
205 * - this method should call key_payload_reserve() to recalculate the 197 * - this method should call key_payload_reserve() to recalculate the
206 * quota consumption 198 * quota consumption
diff --git a/security/keys/key.c b/security/keys/key.c
index 01bcfecb7eae..bb036623d0a8 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -240,9 +240,9 @@ static inline void key_alloc_serial(struct key *key)
240/* 240/*
241 * allocate a key of the specified type 241 * allocate a key of the specified type
242 * - update the user's quota to reflect the existence of the key 242 * - update the user's quota to reflect the existence of the key
243 * - called from a key-type operation with key_types_sem read-locked by either 243 * - called from a key-type operation with key_types_sem read-locked by
244 * key_create_or_update() or by key_duplicate(); this prevents unregistration 244 * key_create_or_update()
245 * of the key type 245 * - this prevents unregistration of the key type
246 * - upon return the key is as yet uninstantiated; the caller needs to either 246 * - upon return the key is as yet uninstantiated; the caller needs to either
247 * instantiate the key or discard it before returning 247 * instantiate the key or discard it before returning
248 */ 248 */
@@ -889,56 +889,6 @@ EXPORT_SYMBOL(key_update);
889 889
890/*****************************************************************************/ 890/*****************************************************************************/
891/* 891/*
892 * duplicate a key, potentially with a revised description
893 * - must be supported by the keytype (keyrings for instance can be duplicated)
894 */
895struct key *key_duplicate(struct key *source, const char *desc)
896{
897 struct key *key;
898 int ret;
899
900 key_check(source);
901
902 if (!desc)
903 desc = source->description;
904
905 down_read(&key_types_sem);
906
907 ret = -EINVAL;
908 if (!source->type->duplicate)
909 goto error;
910
911 /* allocate and instantiate a key */
912 key = key_alloc(source->type, desc, current->fsuid, current->fsgid,
913 source->perm, 0);
914 if (IS_ERR(key))
915 goto error_k;
916
917 down_read(&source->sem);
918 ret = key->type->duplicate(key, source);
919 up_read(&source->sem);
920 if (ret < 0)
921 goto error2;
922
923 atomic_inc(&key->user->nikeys);
924 set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
925
926 error_k:
927 up_read(&key_types_sem);
928 out:
929 return key;
930
931 error2:
932 key_put(key);
933 error:
934 up_read(&key_types_sem);
935 key = ERR_PTR(ret);
936 goto out;
937
938} /* end key_duplicate() */
939
940/*****************************************************************************/
941/*
942 * revoke a key 892 * revoke a key
943 */ 893 */
944void key_revoke(struct key *key) 894void key_revoke(struct key *key)
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 4e9fa8be44b8..0acecbd4fa37 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -48,7 +48,6 @@ static inline unsigned keyring_hash(const char *desc)
48 */ 48 */
49static int keyring_instantiate(struct key *keyring, 49static int keyring_instantiate(struct key *keyring,
50 const void *data, size_t datalen); 50 const void *data, size_t datalen);
51static int keyring_duplicate(struct key *keyring, const struct key *source);
52static int keyring_match(const struct key *keyring, const void *criterion); 51static int keyring_match(const struct key *keyring, const void *criterion);
53static void keyring_destroy(struct key *keyring); 52static void keyring_destroy(struct key *keyring);
54static void keyring_describe(const struct key *keyring, struct seq_file *m); 53static void keyring_describe(const struct key *keyring, struct seq_file *m);
@@ -59,7 +58,6 @@ struct key_type key_type_keyring = {
59 .name = "keyring", 58 .name = "keyring",
60 .def_datalen = sizeof(struct keyring_list), 59 .def_datalen = sizeof(struct keyring_list),
61 .instantiate = keyring_instantiate, 60 .instantiate = keyring_instantiate,
62 .duplicate = keyring_duplicate,
63 .match = keyring_match, 61 .match = keyring_match,
64 .destroy = keyring_destroy, 62 .destroy = keyring_destroy,
65 .describe = keyring_describe, 63 .describe = keyring_describe,
@@ -120,68 +118,6 @@ static int keyring_instantiate(struct key *keyring,
120 118
121/*****************************************************************************/ 119/*****************************************************************************/
122/* 120/*
123 * duplicate the list of subscribed keys from a source keyring into this one
124 */
125static int keyring_duplicate(struct key *keyring, const struct key *source)
126{
127 struct keyring_list *sklist, *klist;
128 unsigned max;
129 size_t size;
130 int loop, ret;
131
132 const unsigned limit =
133 (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key *);
134
135 ret = 0;
136
137 /* find out how many keys are currently linked */
138 rcu_read_lock();
139 sklist = rcu_dereference(source->payload.subscriptions);
140 max = 0;
141 if (sklist)
142 max = sklist->nkeys;
143 rcu_read_unlock();
144
145 /* allocate a new payload and stuff load with key links */
146 if (max > 0) {
147 BUG_ON(max > limit);
148
149 max = (max + 3) & ~3;
150 if (max > limit)
151 max = limit;
152
153 ret = -ENOMEM;
154 size = sizeof(*klist) + sizeof(struct key *) * max;
155 klist = kmalloc(size, GFP_KERNEL);
156 if (!klist)
157 goto error;
158
159 /* set links */
160 rcu_read_lock();
161 sklist = rcu_dereference(source->payload.subscriptions);
162
163 klist->maxkeys = max;
164 klist->nkeys = sklist->nkeys;
165 memcpy(klist->keys,
166 sklist->keys,
167 sklist->nkeys * sizeof(struct key *));
168
169 for (loop = klist->nkeys - 1; loop >= 0; loop--)
170 atomic_inc(&klist->keys[loop]->usage);
171
172 rcu_read_unlock();
173
174 rcu_assign_pointer(keyring->payload.subscriptions, klist);
175 ret = 0;
176 }
177
178 error:
179 return ret;
180
181} /* end keyring_duplicate() */
182
183/*****************************************************************************/
184/*
185 * match keyrings on their name 121 * match keyrings on their name
186 */ 122 */
187static int keyring_match(const struct key *keyring, const void *description) 123static int keyring_match(const struct key *keyring, const void *description)
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index cbda3b2780a1..8e71895b97a7 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -26,7 +26,6 @@
26struct key_type key_type_user = { 26struct key_type key_type_user = {
27 .name = "user", 27 .name = "user",
28 .instantiate = user_instantiate, 28 .instantiate = user_instantiate,
29 .duplicate = user_duplicate,
30 .update = user_update, 29 .update = user_update,
31 .match = user_match, 30 .match = user_match,
32 .destroy = user_destroy, 31 .destroy = user_destroy,
@@ -68,42 +67,10 @@ error:
68 return ret; 67 return ret;
69 68
70} /* end user_instantiate() */ 69} /* end user_instantiate() */
71
72EXPORT_SYMBOL_GPL(user_instantiate); 70EXPORT_SYMBOL_GPL(user_instantiate);
73 71
74/*****************************************************************************/ 72/*****************************************************************************/
75/* 73/*
76 * duplicate a user defined key
77 * - both keys' semaphores are locked against further modification
78 * - the new key cannot yet be accessed
79 */
80int user_duplicate(struct key *key, const struct key *source)
81{
82 struct user_key_payload *upayload, *spayload;
83 int ret;
84
85 /* just copy the payload */
86 ret = -ENOMEM;
87 upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL);
88 if (upayload) {
89 spayload = rcu_dereference(source->payload.data);
90 BUG_ON(source->datalen != spayload->datalen);
91
92 upayload->datalen = key->datalen = spayload->datalen;
93 memcpy(upayload->data, spayload->data, key->datalen);
94
95 key->payload.data = upayload;
96 ret = 0;
97 }
98
99 return ret;
100
101} /* end user_duplicate() */
102
103EXPORT_SYMBOL_GPL(user_duplicate);
104
105/*****************************************************************************/
106/*
107 * dispose of the old data from an updated user defined key 74 * dispose of the old data from an updated user defined key
108 */ 75 */
109static void user_update_rcu_disposal(struct rcu_head *rcu) 76static void user_update_rcu_disposal(struct rcu_head *rcu)