diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/Makefile | 1 | ||||
-rw-r--r-- | security/keys/internal.h | 14 | ||||
-rw-r--r-- | security/keys/key.c | 23 | ||||
-rw-r--r-- | security/keys/keyctl.c | 12 | ||||
-rw-r--r-- | security/keys/proc.c | 9 | ||||
-rw-r--r-- | security/keys/sysctl.c | 50 |
6 files changed, 94 insertions, 15 deletions
diff --git a/security/keys/Makefile b/security/keys/Makefile index 5145adfb6a05..747a464943af 100644 --- a/security/keys/Makefile +++ b/security/keys/Makefile | |||
@@ -14,3 +14,4 @@ obj-y := \ | |||
14 | 14 | ||
15 | obj-$(CONFIG_KEYS_COMPAT) += compat.o | 15 | obj-$(CONFIG_KEYS_COMPAT) += compat.o |
16 | obj-$(CONFIG_PROC_FS) += proc.o | 16 | obj-$(CONFIG_PROC_FS) += proc.o |
17 | obj-$(CONFIG_SYSCTL) += sysctl.o | ||
diff --git a/security/keys/internal.h b/security/keys/internal.h index 2ab38854c47f..8c05587f5018 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -57,10 +57,6 @@ struct key_user { | |||
57 | int qnbytes; /* number of bytes allocated to this user */ | 57 | int qnbytes; /* number of bytes allocated to this user */ |
58 | }; | 58 | }; |
59 | 59 | ||
60 | #define KEYQUOTA_MAX_KEYS 100 | ||
61 | #define KEYQUOTA_MAX_BYTES 10000 | ||
62 | #define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */ | ||
63 | |||
64 | extern struct rb_root key_user_tree; | 60 | extern struct rb_root key_user_tree; |
65 | extern spinlock_t key_user_lock; | 61 | extern spinlock_t key_user_lock; |
66 | extern struct key_user root_key_user; | 62 | extern struct key_user root_key_user; |
@@ -68,6 +64,16 @@ extern struct key_user root_key_user; | |||
68 | extern struct key_user *key_user_lookup(uid_t uid); | 64 | extern struct key_user *key_user_lookup(uid_t uid); |
69 | extern void key_user_put(struct key_user *user); | 65 | extern void key_user_put(struct key_user *user); |
70 | 66 | ||
67 | /* | ||
68 | * key quota limits | ||
69 | * - root has its own separate limits to everyone else | ||
70 | */ | ||
71 | extern unsigned key_quota_root_maxkeys; | ||
72 | extern unsigned key_quota_root_maxbytes; | ||
73 | extern unsigned key_quota_maxkeys; | ||
74 | extern unsigned key_quota_maxbytes; | ||
75 | |||
76 | #define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */ | ||
71 | 77 | ||
72 | 78 | ||
73 | extern struct rb_root key_serial_tree; | 79 | extern struct rb_root key_serial_tree; |
diff --git a/security/keys/key.c b/security/keys/key.c index 46f125aa7fa3..14948cf83ef6 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -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 | ||
@@ -236,11 +241,16 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
236 | /* 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 |
237 | * its description */ | 242 | * its description */ |
238 | 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 | |||
239 | spin_lock(&user->lock); | 249 | spin_lock(&user->lock); |
240 | if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { | 250 | if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { |
241 | if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || | 251 | if (user->qnkeys + 1 >= maxkeys || |
242 | user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES | 252 | user->qnbytes + quotalen >= maxbytes || |
243 | ) | 253 | user->qnbytes + quotalen < user->qnbytes) |
244 | goto no_quota; | 254 | goto no_quota; |
245 | } | 255 | } |
246 | 256 | ||
@@ -345,11 +355,14 @@ int key_payload_reserve(struct key *key, size_t datalen) | |||
345 | 355 | ||
346 | /* contemplate the quota adjustment */ | 356 | /* contemplate the quota adjustment */ |
347 | 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 | |||
348 | spin_lock(&key->user->lock); | 361 | spin_lock(&key->user->lock); |
349 | 362 | ||
350 | if (delta > 0 && | 363 | if (delta > 0 && |
351 | key->user->qnbytes + delta > KEYQUOTA_MAX_BYTES | 364 | (key->user->qnbytes + delta >= maxbytes || |
352 | ) { | 365 | key->user->qnbytes + delta < key->user->qnbytes)) { |
353 | ret = -EDQUOT; | 366 | ret = -EDQUOT; |
354 | } | 367 | } |
355 | else { | 368 | else { |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 993be634a5ef..acc9c89e40a8 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -731,10 +731,16 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
731 | 731 | ||
732 | /* transfer the quota burden to the new user */ | 732 | /* transfer the quota burden to the new user */ |
733 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | 733 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { |
734 | unsigned maxkeys = (uid == 0) ? | ||
735 | key_quota_root_maxkeys : key_quota_maxkeys; | ||
736 | unsigned maxbytes = (uid == 0) ? | ||
737 | key_quota_root_maxbytes : key_quota_maxbytes; | ||
738 | |||
734 | spin_lock(&newowner->lock); | 739 | spin_lock(&newowner->lock); |
735 | if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || | 740 | if (newowner->qnkeys + 1 >= maxkeys || |
736 | newowner->qnbytes + key->quotalen >= | 741 | newowner->qnbytes + key->quotalen >= maxbytes || |
737 | KEYQUOTA_MAX_BYTES) | 742 | newowner->qnbytes + key->quotalen < |
743 | newowner->qnbytes) | ||
738 | goto quota_overrun; | 744 | goto quota_overrun; |
739 | 745 | ||
740 | newowner->qnkeys++; | 746 | newowner->qnkeys++; |
diff --git a/security/keys/proc.c b/security/keys/proc.c index e54679b848cf..f619170da760 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -242,6 +242,10 @@ static int proc_key_users_show(struct seq_file *m, void *v) | |||
242 | { | 242 | { |
243 | struct rb_node *_p = v; | 243 | struct rb_node *_p = v; |
244 | struct key_user *user = rb_entry(_p, struct key_user, node); | 244 | struct key_user *user = rb_entry(_p, struct key_user, node); |
245 | unsigned maxkeys = (user->uid == 0) ? | ||
246 | key_quota_root_maxkeys : key_quota_maxkeys; | ||
247 | unsigned maxbytes = (user->uid == 0) ? | ||
248 | key_quota_root_maxbytes : key_quota_maxbytes; | ||
245 | 249 | ||
246 | seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", | 250 | seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", |
247 | user->uid, | 251 | user->uid, |
@@ -249,10 +253,9 @@ static int proc_key_users_show(struct seq_file *m, void *v) | |||
249 | atomic_read(&user->nkeys), | 253 | atomic_read(&user->nkeys), |
250 | atomic_read(&user->nikeys), | 254 | atomic_read(&user->nikeys), |
251 | user->qnkeys, | 255 | user->qnkeys, |
252 | KEYQUOTA_MAX_KEYS, | 256 | maxkeys, |
253 | user->qnbytes, | 257 | user->qnbytes, |
254 | KEYQUOTA_MAX_BYTES | 258 | maxbytes); |
255 | ); | ||
256 | 259 | ||
257 | return 0; | 260 | return 0; |
258 | 261 | ||
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c new file mode 100644 index 000000000000..b611d493c2d8 --- /dev/null +++ b/security/keys/sysctl.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* Key management controls | ||
2 | * | ||
3 | * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/key.h> | ||
13 | #include <linux/sysctl.h> | ||
14 | #include "internal.h" | ||
15 | |||
16 | ctl_table key_sysctls[] = { | ||
17 | { | ||
18 | .ctl_name = CTL_UNNUMBERED, | ||
19 | .procname = "maxkeys", | ||
20 | .data = &key_quota_maxkeys, | ||
21 | .maxlen = sizeof(unsigned), | ||
22 | .mode = 0644, | ||
23 | .proc_handler = &proc_dointvec, | ||
24 | }, | ||
25 | { | ||
26 | .ctl_name = CTL_UNNUMBERED, | ||
27 | .procname = "maxbytes", | ||
28 | .data = &key_quota_maxbytes, | ||
29 | .maxlen = sizeof(unsigned), | ||
30 | .mode = 0644, | ||
31 | .proc_handler = &proc_dointvec, | ||
32 | }, | ||
33 | { | ||
34 | .ctl_name = CTL_UNNUMBERED, | ||
35 | .procname = "root_maxkeys", | ||
36 | .data = &key_quota_root_maxkeys, | ||
37 | .maxlen = sizeof(unsigned), | ||
38 | .mode = 0644, | ||
39 | .proc_handler = &proc_dointvec, | ||
40 | }, | ||
41 | { | ||
42 | .ctl_name = CTL_UNNUMBERED, | ||
43 | .procname = "root_maxbytes", | ||
44 | .data = &key_quota_root_maxbytes, | ||
45 | .maxlen = sizeof(unsigned), | ||
46 | .mode = 0644, | ||
47 | .proc_handler = &proc_dointvec, | ||
48 | }, | ||
49 | { .ctl_name = 0 } | ||
50 | }; | ||