aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-06-26 03:24:50 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:18 -0400
commit7e047ef5fe2d52e83020e856b1bf2556a6a2ce98 (patch)
tree97656e2c56a27be9d1da451dde627b693b8643f2 /security
parentf116629d03655adaf7832b93b03c99391d09d4a7 (diff)
[PATCH] keys: sort out key quota system
Add the ability for key creation to overrun the user's quota in some circumstances - notably when a session keyring is created and assigned to a process that didn't previously have one. This means it's still possible to log in, should PAM require the creation of a new session keyring, and fix an overburdened key quota. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c3
-rw-r--r--security/keys/internal.h3
-rw-r--r--security/keys/key.c26
-rw-r--r--security/keys/keyctl.c5
-rw-r--r--security/keys/keyring.c4
-rw-r--r--security/keys/process_keys.c24
-rw-r--r--security/keys/request_key.c36
-rw-r--r--security/keys/request_key_auth.c2
-rw-r--r--security/selinux/hooks.c9
9 files changed, 68 insertions, 44 deletions
diff --git a/security/dummy.c b/security/dummy.c
index c3c5493581e2..310fcdf7b749 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -870,7 +870,8 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz
870} 870}
871 871
872#ifdef CONFIG_KEYS 872#ifdef CONFIG_KEYS
873static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx) 873static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
874 unsigned long flags)
874{ 875{
875 return 0; 876 return 0;
876} 877}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index e066e6057955..3c2877f0663e 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -99,7 +99,8 @@ extern int install_process_keyring(struct task_struct *tsk);
99extern struct key *request_key_and_link(struct key_type *type, 99extern struct key *request_key_and_link(struct key_type *type,
100 const char *description, 100 const char *description,
101 const char *callout_info, 101 const char *callout_info,
102 struct key *dest_keyring); 102 struct key *dest_keyring,
103 unsigned long flags);
103 104
104/* 105/*
105 * request_key authorisation 106 * request_key authorisation
diff --git a/security/keys/key.c b/security/keys/key.c
index 51f851557389..3601fddca9f2 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -248,7 +248,7 @@ static inline void key_alloc_serial(struct key *key)
248 */ 248 */
249struct key *key_alloc(struct key_type *type, const char *desc, 249struct key *key_alloc(struct key_type *type, const char *desc,
250 uid_t uid, gid_t gid, struct task_struct *ctx, 250 uid_t uid, gid_t gid, struct task_struct *ctx,
251 key_perm_t perm, int not_in_quota) 251 key_perm_t perm, unsigned long flags)
252{ 252{
253 struct key_user *user = NULL; 253 struct key_user *user = NULL;
254 struct key *key; 254 struct key *key;
@@ -269,12 +269,14 @@ struct key *key_alloc(struct key_type *type, const char *desc,
269 269
270 /* check that the user's quota permits allocation of another key and 270 /* check that the user's quota permits allocation of another key and
271 * its description */ 271 * its description */
272 if (!not_in_quota) { 272 if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
273 spin_lock(&user->lock); 273 spin_lock(&user->lock);
274 if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || 274 if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
275 user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES 275 if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
276 ) 276 user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
277 goto no_quota; 277 )
278 goto no_quota;
279 }
278 280
279 user->qnkeys++; 281 user->qnkeys++;
280 user->qnbytes += quotalen; 282 user->qnbytes += quotalen;
@@ -308,7 +310,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
308 key->payload.data = NULL; 310 key->payload.data = NULL;
309 key->security = NULL; 311 key->security = NULL;
310 312
311 if (!not_in_quota) 313 if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
312 key->flags |= 1 << KEY_FLAG_IN_QUOTA; 314 key->flags |= 1 << KEY_FLAG_IN_QUOTA;
313 315
314 memset(&key->type_data, 0, sizeof(key->type_data)); 316 memset(&key->type_data, 0, sizeof(key->type_data));
@@ -318,7 +320,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
318#endif 320#endif
319 321
320 /* let the security module know about the key */ 322 /* let the security module know about the key */
321 ret = security_key_alloc(key, ctx); 323 ret = security_key_alloc(key, ctx, flags);
322 if (ret < 0) 324 if (ret < 0)
323 goto security_error; 325 goto security_error;
324 326
@@ -332,7 +334,7 @@ error:
332security_error: 334security_error:
333 kfree(key->description); 335 kfree(key->description);
334 kmem_cache_free(key_jar, key); 336 kmem_cache_free(key_jar, key);
335 if (!not_in_quota) { 337 if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
336 spin_lock(&user->lock); 338 spin_lock(&user->lock);
337 user->qnkeys--; 339 user->qnkeys--;
338 user->qnbytes -= quotalen; 340 user->qnbytes -= quotalen;
@@ -345,7 +347,7 @@ security_error:
345no_memory_3: 347no_memory_3:
346 kmem_cache_free(key_jar, key); 348 kmem_cache_free(key_jar, key);
347no_memory_2: 349no_memory_2:
348 if (!not_in_quota) { 350 if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
349 spin_lock(&user->lock); 351 spin_lock(&user->lock);
350 user->qnkeys--; 352 user->qnkeys--;
351 user->qnbytes -= quotalen; 353 user->qnbytes -= quotalen;
@@ -761,7 +763,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
761 const char *description, 763 const char *description,
762 const void *payload, 764 const void *payload,
763 size_t plen, 765 size_t plen,
764 int not_in_quota) 766 unsigned long flags)
765{ 767{
766 struct key_type *ktype; 768 struct key_type *ktype;
767 struct key *keyring, *key = NULL; 769 struct key *keyring, *key = NULL;
@@ -822,7 +824,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
822 824
823 /* allocate a new key */ 825 /* allocate a new key */
824 key = key_alloc(ktype, description, current->fsuid, current->fsgid, 826 key = key_alloc(ktype, description, current->fsuid, current->fsgid,
825 current, perm, not_in_quota); 827 current, perm, flags);
826 if (IS_ERR(key)) { 828 if (IS_ERR(key)) {
827 key_ref = ERR_PTR(PTR_ERR(key)); 829 key_ref = ERR_PTR(PTR_ERR(key));
828 goto error_3; 830 goto error_3;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index ed71d86d2ce2..d74458522e98 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -102,7 +102,7 @@ asmlinkage long sys_add_key(const char __user *_type,
102 /* create or update the requested key and add it to the target 102 /* create or update the requested key and add it to the target
103 * keyring */ 103 * keyring */
104 key_ref = key_create_or_update(keyring_ref, type, description, 104 key_ref = key_create_or_update(keyring_ref, type, description,
105 payload, plen, 0); 105 payload, plen, KEY_ALLOC_IN_QUOTA);
106 if (!IS_ERR(key_ref)) { 106 if (!IS_ERR(key_ref)) {
107 ret = key_ref_to_ptr(key_ref)->serial; 107 ret = key_ref_to_ptr(key_ref)->serial;
108 key_ref_put(key_ref); 108 key_ref_put(key_ref);
@@ -184,7 +184,8 @@ asmlinkage long sys_request_key(const char __user *_type,
184 184
185 /* do the search */ 185 /* do the search */
186 key = request_key_and_link(ktype, description, callout_info, 186 key = request_key_and_link(ktype, description, callout_info,
187 key_ref_to_ptr(dest_ref)); 187 key_ref_to_ptr(dest_ref),
188 KEY_ALLOC_IN_QUOTA);
188 if (IS_ERR(key)) { 189 if (IS_ERR(key)) {
189 ret = PTR_ERR(key); 190 ret = PTR_ERR(key);
190 goto error5; 191 goto error5;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 1357207fc9df..6c282bd937e2 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -240,7 +240,7 @@ static long keyring_read(const struct key *keyring,
240 * allocate a keyring and link into the destination keyring 240 * allocate a keyring and link into the destination keyring
241 */ 241 */
242struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, 242struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
243 struct task_struct *ctx, int not_in_quota, 243 struct task_struct *ctx, unsigned long flags,
244 struct key *dest) 244 struct key *dest)
245{ 245{
246 struct key *keyring; 246 struct key *keyring;
@@ -249,7 +249,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
249 keyring = key_alloc(&key_type_keyring, description, 249 keyring = key_alloc(&key_type_keyring, description,
250 uid, gid, ctx, 250 uid, gid, ctx,
251 (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, 251 (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
252 not_in_quota); 252 flags);
253 253
254 if (!IS_ERR(keyring)) { 254 if (!IS_ERR(keyring)) {
255 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); 255 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 4d9825f9962c..32150cf7c37f 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -77,7 +77,8 @@ int alloc_uid_keyring(struct user_struct *user,
77 /* concoct a default session keyring */ 77 /* concoct a default session keyring */
78 sprintf(buf, "_uid_ses.%u", user->uid); 78 sprintf(buf, "_uid_ses.%u", user->uid);
79 79
80 session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); 80 session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
81 KEY_ALLOC_IN_QUOTA, NULL);
81 if (IS_ERR(session_keyring)) { 82 if (IS_ERR(session_keyring)) {
82 ret = PTR_ERR(session_keyring); 83 ret = PTR_ERR(session_keyring);
83 goto error; 84 goto error;
@@ -87,8 +88,8 @@ int alloc_uid_keyring(struct user_struct *user,
87 * keyring */ 88 * keyring */
88 sprintf(buf, "_uid.%u", user->uid); 89 sprintf(buf, "_uid.%u", user->uid);
89 90
90 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, 91 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
91 session_keyring); 92 KEY_ALLOC_IN_QUOTA, session_keyring);
92 if (IS_ERR(uid_keyring)) { 93 if (IS_ERR(uid_keyring)) {
93 key_put(session_keyring); 94 key_put(session_keyring);
94 ret = PTR_ERR(uid_keyring); 95 ret = PTR_ERR(uid_keyring);
@@ -144,7 +145,8 @@ int install_thread_keyring(struct task_struct *tsk)
144 145
145 sprintf(buf, "_tid.%u", tsk->pid); 146 sprintf(buf, "_tid.%u", tsk->pid);
146 147
147 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); 148 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
149 KEY_ALLOC_QUOTA_OVERRUN, NULL);
148 if (IS_ERR(keyring)) { 150 if (IS_ERR(keyring)) {
149 ret = PTR_ERR(keyring); 151 ret = PTR_ERR(keyring);
150 goto error; 152 goto error;
@@ -178,7 +180,8 @@ int install_process_keyring(struct task_struct *tsk)
178 if (!tsk->signal->process_keyring) { 180 if (!tsk->signal->process_keyring) {
179 sprintf(buf, "_pid.%u", tsk->tgid); 181 sprintf(buf, "_pid.%u", tsk->tgid);
180 182
181 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); 183 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
184 KEY_ALLOC_QUOTA_OVERRUN, NULL);
182 if (IS_ERR(keyring)) { 185 if (IS_ERR(keyring)) {
183 ret = PTR_ERR(keyring); 186 ret = PTR_ERR(keyring);
184 goto error; 187 goto error;
@@ -209,6 +212,7 @@ error:
209static int install_session_keyring(struct task_struct *tsk, 212static int install_session_keyring(struct task_struct *tsk,
210 struct key *keyring) 213 struct key *keyring)
211{ 214{
215 unsigned long flags;
212 struct key *old; 216 struct key *old;
213 char buf[20]; 217 char buf[20];
214 218
@@ -218,7 +222,12 @@ static int install_session_keyring(struct task_struct *tsk,
218 if (!keyring) { 222 if (!keyring) {
219 sprintf(buf, "_ses.%u", tsk->tgid); 223 sprintf(buf, "_ses.%u", tsk->tgid);
220 224
221 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); 225 flags = KEY_ALLOC_QUOTA_OVERRUN;
226 if (tsk->signal->session_keyring)
227 flags = KEY_ALLOC_IN_QUOTA;
228
229 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
230 flags, NULL);
222 if (IS_ERR(keyring)) 231 if (IS_ERR(keyring))
223 return PTR_ERR(keyring); 232 return PTR_ERR(keyring);
224 } 233 }
@@ -728,7 +737,8 @@ long join_session_keyring(const char *name)
728 keyring = find_keyring_by_name(name, 0); 737 keyring = find_keyring_by_name(name, 0);
729 if (PTR_ERR(keyring) == -ENOKEY) { 738 if (PTR_ERR(keyring) == -ENOKEY) {
730 /* not found - try and create a new one */ 739 /* not found - try and create a new one */
731 keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); 740 keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
741 KEY_ALLOC_IN_QUOTA, NULL);
732 if (IS_ERR(keyring)) { 742 if (IS_ERR(keyring)) {
733 ret = PTR_ERR(keyring); 743 ret = PTR_ERR(keyring);
734 goto error2; 744 goto error2;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index eab66a06ca53..58d1efd4fc2c 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -48,8 +48,8 @@ static int call_sbin_request_key(struct key *key,
48 /* allocate a new session keyring */ 48 /* allocate a new session keyring */
49 sprintf(desc, "_req.%u", key->serial); 49 sprintf(desc, "_req.%u", key->serial);
50 50
51 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 51 keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
52 current, 1, NULL); 52 KEY_ALLOC_QUOTA_OVERRUN, NULL);
53 if (IS_ERR(keyring)) { 53 if (IS_ERR(keyring)) {
54 ret = PTR_ERR(keyring); 54 ret = PTR_ERR(keyring);
55 goto error_alloc; 55 goto error_alloc;
@@ -126,7 +126,8 @@ error_alloc:
126 */ 126 */
127static struct key *__request_key_construction(struct key_type *type, 127static struct key *__request_key_construction(struct key_type *type,
128 const char *description, 128 const char *description,
129 const char *callout_info) 129 const char *callout_info,
130 unsigned long flags)
130{ 131{
131 request_key_actor_t actor; 132 request_key_actor_t actor;
132 struct key_construction cons; 133 struct key_construction cons;
@@ -134,12 +135,12 @@ static struct key *__request_key_construction(struct key_type *type,
134 struct key *key, *authkey; 135 struct key *key, *authkey;
135 int ret, negated; 136 int ret, negated;
136 137
137 kenter("%s,%s,%s", type->name, description, callout_info); 138 kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags);
138 139
139 /* create a key and add it to the queue */ 140 /* create a key and add it to the queue */
140 key = key_alloc(type, description, 141 key = key_alloc(type, description,
141 current->fsuid, current->fsgid, 142 current->fsuid, current->fsgid, current, KEY_POS_ALL,
142 current, KEY_POS_ALL, 0); 143 flags);
143 if (IS_ERR(key)) 144 if (IS_ERR(key))
144 goto alloc_failed; 145 goto alloc_failed;
145 146
@@ -258,15 +259,16 @@ alloc_failed:
258static struct key *request_key_construction(struct key_type *type, 259static struct key *request_key_construction(struct key_type *type,
259 const char *description, 260 const char *description,
260 struct key_user *user, 261 struct key_user *user,
261 const char *callout_info) 262 const char *callout_info,
263 unsigned long flags)
262{ 264{
263 struct key_construction *pcons; 265 struct key_construction *pcons;
264 struct key *key, *ckey; 266 struct key *key, *ckey;
265 267
266 DECLARE_WAITQUEUE(myself, current); 268 DECLARE_WAITQUEUE(myself, current);
267 269
268 kenter("%s,%s,{%d},%s", 270 kenter("%s,%s,{%d},%s,%lx",
269 type->name, description, user->uid, callout_info); 271 type->name, description, user->uid, callout_info, flags);
270 272
271 /* see if there's such a key under construction already */ 273 /* see if there's such a key under construction already */
272 down_write(&key_construction_sem); 274 down_write(&key_construction_sem);
@@ -282,7 +284,8 @@ static struct key *request_key_construction(struct key_type *type,
282 } 284 }
283 285
284 /* see about getting userspace to construct the key */ 286 /* see about getting userspace to construct the key */
285 key = __request_key_construction(type, description, callout_info); 287 key = __request_key_construction(type, description, callout_info,
288 flags);
286 error: 289 error:
287 kleave(" = %p", key); 290 kleave(" = %p", key);
288 return key; 291 return key;
@@ -389,14 +392,15 @@ static void request_key_link(struct key *key, struct key *dest_keyring)
389struct key *request_key_and_link(struct key_type *type, 392struct key *request_key_and_link(struct key_type *type,
390 const char *description, 393 const char *description,
391 const char *callout_info, 394 const char *callout_info,
392 struct key *dest_keyring) 395 struct key *dest_keyring,
396 unsigned long flags)
393{ 397{
394 struct key_user *user; 398 struct key_user *user;
395 struct key *key; 399 struct key *key;
396 key_ref_t key_ref; 400 key_ref_t key_ref;
397 401
398 kenter("%s,%s,%s,%p", 402 kenter("%s,%s,%s,%p,%lx",
399 type->name, description, callout_info, dest_keyring); 403 type->name, description, callout_info, dest_keyring, flags);
400 404
401 /* search all the process keyrings for a key */ 405 /* search all the process keyrings for a key */
402 key_ref = search_process_keyrings(type, description, type->match, 406 key_ref = search_process_keyrings(type, description, type->match,
@@ -429,7 +433,8 @@ struct key *request_key_and_link(struct key_type *type,
429 /* ask userspace (returns NULL if it waited on a key 433 /* ask userspace (returns NULL if it waited on a key
430 * being constructed) */ 434 * being constructed) */
431 key = request_key_construction(type, description, 435 key = request_key_construction(type, description,
432 user, callout_info); 436 user, callout_info,
437 flags);
433 if (key) 438 if (key)
434 break; 439 break;
435 440
@@ -485,7 +490,8 @@ struct key *request_key(struct key_type *type,
485 const char *description, 490 const char *description,
486 const char *callout_info) 491 const char *callout_info)
487{ 492{
488 return request_key_and_link(type, description, callout_info, NULL); 493 return request_key_and_link(type, description, callout_info, NULL,
494 KEY_ALLOC_IN_QUOTA);
489 495
490} /* end request_key() */ 496} /* end request_key() */
491 497
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index cb9817ced3fd..cbf58a91b00a 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -187,7 +187,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
187 authkey = key_alloc(&key_type_request_key_auth, desc, 187 authkey = key_alloc(&key_type_request_key_auth, desc,
188 current->fsuid, current->fsgid, current, 188 current->fsuid, current->fsgid, current,
189 KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | 189 KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
190 KEY_USR_VIEW, 1); 190 KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
191 if (IS_ERR(authkey)) { 191 if (IS_ERR(authkey)) {
192 ret = PTR_ERR(authkey); 192 ret = PTR_ERR(authkey);
193 goto error_alloc; 193 goto error_alloc;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 79c16e31c884..13384fef0d60 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4264,7 +4264,8 @@ static int selinux_setprocattr(struct task_struct *p,
4264 4264
4265#ifdef CONFIG_KEYS 4265#ifdef CONFIG_KEYS
4266 4266
4267static int selinux_key_alloc(struct key *k, struct task_struct *tsk) 4267static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
4268 unsigned long flags)
4268{ 4269{
4269 struct task_security_struct *tsec = tsk->security; 4270 struct task_security_struct *tsec = tsk->security;
4270 struct key_security_struct *ksec; 4271 struct key_security_struct *ksec;
@@ -4513,8 +4514,10 @@ static __init int selinux_init(void)
4513 4514
4514#ifdef CONFIG_KEYS 4515#ifdef CONFIG_KEYS
4515 /* Add security information to initial keyrings */ 4516 /* Add security information to initial keyrings */
4516 security_key_alloc(&root_user_keyring, current); 4517 security_key_alloc(&root_user_keyring, current,
4517 security_key_alloc(&root_session_keyring, current); 4518 KEY_ALLOC_NOT_IN_QUOTA);
4519 security_key_alloc(&root_session_keyring, current,
4520 KEY_ALLOC_NOT_IN_QUOTA);
4518#endif 4521#endif
4519 4522
4520 return 0; 4523 return 0;