diff options
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 86 |
1 files changed, 29 insertions, 57 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index 654d23baf352..14948cf83ef6 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Basic authentication token and access key management | 1 | /* Basic authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -27,6 +27,11 @@ DEFINE_SPINLOCK(key_serial_lock); | |||
27 | struct rb_root key_user_tree; /* tree of quota records indexed by UID */ | 27 | struct rb_root key_user_tree; /* tree of quota records indexed by UID */ |
28 | DEFINE_SPINLOCK(key_user_lock); | 28 | DEFINE_SPINLOCK(key_user_lock); |
29 | 29 | ||
30 | unsigned int key_quota_root_maxkeys = 200; /* root's key count quota */ | ||
31 | unsigned int key_quota_root_maxbytes = 20000; /* root's key space quota */ | ||
32 | unsigned int key_quota_maxkeys = 200; /* general key count quota */ | ||
33 | unsigned int key_quota_maxbytes = 20000; /* general key space quota */ | ||
34 | |||
30 | static LIST_HEAD(key_types_list); | 35 | static LIST_HEAD(key_types_list); |
31 | static DECLARE_RWSEM(key_types_sem); | 36 | static DECLARE_RWSEM(key_types_sem); |
32 | 37 | ||
@@ -139,36 +144,6 @@ void key_user_put(struct key_user *user) | |||
139 | 144 | ||
140 | /*****************************************************************************/ | 145 | /*****************************************************************************/ |
141 | /* | 146 | /* |
142 | * insert a key with a fixed serial number | ||
143 | */ | ||
144 | static void __init __key_insert_serial(struct key *key) | ||
145 | { | ||
146 | struct rb_node *parent, **p; | ||
147 | struct key *xkey; | ||
148 | |||
149 | parent = NULL; | ||
150 | p = &key_serial_tree.rb_node; | ||
151 | |||
152 | while (*p) { | ||
153 | parent = *p; | ||
154 | xkey = rb_entry(parent, struct key, serial_node); | ||
155 | |||
156 | if (key->serial < xkey->serial) | ||
157 | p = &(*p)->rb_left; | ||
158 | else if (key->serial > xkey->serial) | ||
159 | p = &(*p)->rb_right; | ||
160 | else | ||
161 | BUG(); | ||
162 | } | ||
163 | |||
164 | /* we've found a suitable hole - arrange for this key to occupy it */ | ||
165 | rb_link_node(&key->serial_node, parent, p); | ||
166 | rb_insert_color(&key->serial_node, &key_serial_tree); | ||
167 | |||
168 | } /* end __key_insert_serial() */ | ||
169 | |||
170 | /*****************************************************************************/ | ||
171 | /* | ||
172 | * assign a key the next unique serial number | 147 | * assign a key the next unique serial number |
173 | * - these are assigned randomly to avoid security issues through covert | 148 | * - these are assigned randomly to avoid security issues through covert |
174 | * channel problems | 149 | * channel problems |
@@ -266,11 +241,16 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
266 | /* check that the user's quota permits allocation of another key and | 241 | /* check that the user's quota permits allocation of another key and |
267 | * its description */ | 242 | * its description */ |
268 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { | 243 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
244 | unsigned maxkeys = (uid == 0) ? | ||
245 | key_quota_root_maxkeys : key_quota_maxkeys; | ||
246 | unsigned maxbytes = (uid == 0) ? | ||
247 | key_quota_root_maxbytes : key_quota_maxbytes; | ||
248 | |||
269 | spin_lock(&user->lock); | 249 | spin_lock(&user->lock); |
270 | if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { | 250 | if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { |
271 | if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || | 251 | if (user->qnkeys + 1 >= maxkeys || |
272 | user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES | 252 | user->qnbytes + quotalen >= maxbytes || |
273 | ) | 253 | user->qnbytes + quotalen < user->qnbytes) |
274 | goto no_quota; | 254 | goto no_quota; |
275 | } | 255 | } |
276 | 256 | ||
@@ -375,11 +355,14 @@ int key_payload_reserve(struct key *key, size_t datalen) | |||
375 | 355 | ||
376 | /* contemplate the quota adjustment */ | 356 | /* contemplate the quota adjustment */ |
377 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 357 | if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
358 | unsigned maxbytes = (key->user->uid == 0) ? | ||
359 | key_quota_root_maxbytes : key_quota_maxbytes; | ||
360 | |||
378 | spin_lock(&key->user->lock); | 361 | spin_lock(&key->user->lock); |
379 | 362 | ||
380 | if (delta > 0 && | 363 | if (delta > 0 && |
381 | key->user->qnbytes + delta > KEYQUOTA_MAX_BYTES | 364 | (key->user->qnbytes + delta >= maxbytes || |
382 | ) { | 365 | key->user->qnbytes + delta < key->user->qnbytes)) { |
383 | ret = -EDQUOT; | 366 | ret = -EDQUOT; |
384 | } | 367 | } |
385 | else { | 368 | else { |
@@ -757,11 +740,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
757 | const char *description, | 740 | const char *description, |
758 | const void *payload, | 741 | const void *payload, |
759 | size_t plen, | 742 | size_t plen, |
743 | key_perm_t perm, | ||
760 | unsigned long flags) | 744 | unsigned long flags) |
761 | { | 745 | { |
762 | struct key_type *ktype; | 746 | struct key_type *ktype; |
763 | struct key *keyring, *key = NULL; | 747 | struct key *keyring, *key = NULL; |
764 | key_perm_t perm; | ||
765 | key_ref_t key_ref; | 748 | key_ref_t key_ref; |
766 | int ret; | 749 | int ret; |
767 | 750 | ||
@@ -806,15 +789,17 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
806 | goto found_matching_key; | 789 | goto found_matching_key; |
807 | } | 790 | } |
808 | 791 | ||
809 | /* decide on the permissions we want */ | 792 | /* if the client doesn't provide, decide on the permissions we want */ |
810 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | 793 | if (perm == KEY_PERM_UNDEF) { |
811 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; | 794 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
795 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; | ||
812 | 796 | ||
813 | if (ktype->read) | 797 | if (ktype->read) |
814 | perm |= KEY_POS_READ | KEY_USR_READ; | 798 | perm |= KEY_POS_READ | KEY_USR_READ; |
815 | 799 | ||
816 | if (ktype == &key_type_keyring || ktype->update) | 800 | if (ktype == &key_type_keyring || ktype->update) |
817 | perm |= KEY_USR_WRITE; | 801 | perm |= KEY_USR_WRITE; |
802 | } | ||
818 | 803 | ||
819 | /* allocate a new key */ | 804 | /* allocate a new key */ |
820 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, | 805 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, |
@@ -1018,17 +1003,4 @@ void __init key_init(void) | |||
1018 | rb_insert_color(&root_key_user.node, | 1003 | rb_insert_color(&root_key_user.node, |
1019 | &key_user_tree); | 1004 | &key_user_tree); |
1020 | 1005 | ||
1021 | /* record root's user standard keyrings */ | ||
1022 | key_check(&root_user_keyring); | ||
1023 | key_check(&root_session_keyring); | ||
1024 | |||
1025 | __key_insert_serial(&root_user_keyring); | ||
1026 | __key_insert_serial(&root_session_keyring); | ||
1027 | |||
1028 | keyring_publish_name(&root_user_keyring); | ||
1029 | keyring_publish_name(&root_session_keyring); | ||
1030 | |||
1031 | /* link the two root keyrings together */ | ||
1032 | key_link(&root_session_keyring, &root_user_keyring); | ||
1033 | |||
1034 | } /* end key_init() */ | 1006 | } /* end key_init() */ |