aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/keys/Makefile1
-rw-r--r--security/keys/internal.h14
-rw-r--r--security/keys/key.c23
-rw-r--r--security/keys/keyctl.c12
-rw-r--r--security/keys/proc.c9
-rw-r--r--security/keys/sysctl.c50
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
15obj-$(CONFIG_KEYS_COMPAT) += compat.o 15obj-$(CONFIG_KEYS_COMPAT) += compat.o
16obj-$(CONFIG_PROC_FS) += proc.o 16obj-$(CONFIG_PROC_FS) += proc.o
17obj-$(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
64extern struct rb_root key_user_tree; 60extern struct rb_root key_user_tree;
65extern spinlock_t key_user_lock; 61extern spinlock_t key_user_lock;
66extern struct key_user root_key_user; 62extern struct key_user root_key_user;
@@ -68,6 +64,16 @@ extern struct key_user root_key_user;
68extern struct key_user *key_user_lookup(uid_t uid); 64extern struct key_user *key_user_lookup(uid_t uid);
69extern void key_user_put(struct key_user *user); 65extern 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 */
71extern unsigned key_quota_root_maxkeys;
72extern unsigned key_quota_root_maxbytes;
73extern unsigned key_quota_maxkeys;
74extern unsigned key_quota_maxbytes;
75
76#define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */
71 77
72 78
73extern struct rb_root key_serial_tree; 79extern 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);
27struct rb_root key_user_tree; /* tree of quota records indexed by UID */ 27struct rb_root key_user_tree; /* tree of quota records indexed by UID */
28DEFINE_SPINLOCK(key_user_lock); 28DEFINE_SPINLOCK(key_user_lock);
29 29
30unsigned int key_quota_root_maxkeys = 200; /* root's key count quota */
31unsigned int key_quota_root_maxbytes = 20000; /* root's key space quota */
32unsigned int key_quota_maxkeys = 200; /* general key count quota */
33unsigned int key_quota_maxbytes = 20000; /* general key space quota */
34
30static LIST_HEAD(key_types_list); 35static LIST_HEAD(key_types_list);
31static DECLARE_RWSEM(key_types_sem); 36static 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
16ctl_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};