Skip to content

Commit 0b77f5b

Browse files
dhowellstorvalds
authored andcommitted
keys: make the keyring quotas controllable through /proc/sys
Make the keyring quotas controllable through /proc/sys files: (*) /proc/sys/kernel/keys/root_maxkeys /proc/sys/kernel/keys/root_maxbytes Maximum number of keys that root may have and the maximum total number of bytes of data that root may have stored in those keys. (*) /proc/sys/kernel/keys/maxkeys /proc/sys/kernel/keys/maxbytes Maximum number of keys that each non-root user may have and the maximum total number of bytes of data that each of those users may have stored in their keys. Also increase the quotas as a number of people have been complaining that it's not big enough. I'm not sure that it's big enough now either, but on the other hand, it can now be set in /etc/sysctl.conf. Signed-off-by: David Howells <dhowells@redhat.com> Cc: <kwc@citi.umich.edu> Cc: <arunsr@cse.iitk.ac.in> Cc: <dwalsh@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 69664cf commit 0b77f5b

File tree

9 files changed

+131
-16
lines changed

9 files changed

+131
-16
lines changed

Documentation/keys.txt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ The key service provides a number of features besides keys:
170170
amount of description and payload space that can be consumed.
171171

172172
The user can view information on this and other statistics through procfs
173-
files.
173+
files. The root user may also alter the quota limits through sysctl files
174+
(see the section "New procfs files").
174175

175176
Process-specific and thread-specific keyrings are not counted towards a
176177
user's quota.
@@ -329,6 +330,27 @@ about the status of the key service:
329330
<bytes>/<max> Key size quota
330331

331332

333+
Four new sysctl files have been added also for the purpose of controlling the
334+
quota limits on keys:
335+
336+
(*) /proc/sys/kernel/keys/root_maxkeys
337+
/proc/sys/kernel/keys/root_maxbytes
338+
339+
These files hold the maximum number of keys that root may have and the
340+
maximum total number of bytes of data that root may have stored in those
341+
keys.
342+
343+
(*) /proc/sys/kernel/keys/maxkeys
344+
/proc/sys/kernel/keys/maxbytes
345+
346+
These files hold the maximum number of keys that each non-root user may
347+
have and the maximum total number of bytes of data that each of those
348+
users may have stored in their keys.
349+
350+
Root may alter these by writing each new limit as a decimal number string to
351+
the appropriate file.
352+
353+
332354
===============================
333355
USERSPACE SYSTEM CALL INTERFACE
334356
===============================

include/linux/key.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/list.h>
2020
#include <linux/rbtree.h>
2121
#include <linux/rcupdate.h>
22+
#include <linux/sysctl.h>
2223
#include <asm/atomic.h>
2324

2425
#ifdef __KERNEL__
@@ -265,6 +266,10 @@ extern struct key *key_lookup(key_serial_t id);
265266

266267
#define key_serial(key) ((key) ? (key)->serial : 0)
267268

269+
#ifdef CONFIG_SYSCTL
270+
extern ctl_table key_sysctls[];
271+
#endif
272+
268273
/*
269274
* the userspace interface
270275
*/

kernel/sysctl.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/writeback.h>
3939
#include <linux/hugetlb.h>
4040
#include <linux/initrd.h>
41+
#include <linux/key.h>
4142
#include <linux/times.h>
4243
#include <linux/limits.h>
4344
#include <linux/dcache.h>
@@ -809,6 +810,14 @@ static struct ctl_table kern_table[] = {
809810
.proc_handler = &proc_dostring,
810811
.strategy = &sysctl_string,
811812
},
813+
#ifdef CONFIG_KEYS
814+
{
815+
.ctl_name = CTL_UNNUMBERED,
816+
.procname = "keys",
817+
.mode = 0555,
818+
.child = key_sysctls,
819+
},
820+
#endif
812821
/*
813822
* NOTE: do not add new entries to this table unless you have read
814823
* Documentation/sysctl/ctl_unnumbered.txt

security/keys/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ obj-y := \
1414

1515
obj-$(CONFIG_KEYS_COMPAT) += compat.o
1616
obj-$(CONFIG_PROC_FS) += proc.o
17+
obj-$(CONFIG_SYSCTL) += sysctl.o

security/keys/internal.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,23 @@ struct key_user {
5757
int qnbytes; /* number of bytes allocated to this user */
5858
};
5959

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-
6460
extern struct rb_root key_user_tree;
6561
extern spinlock_t key_user_lock;
6662
extern struct key_user root_key_user;
6763

6864
extern struct key_user *key_user_lookup(uid_t uid);
6965
extern void key_user_put(struct key_user *user);
7066

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 */
7177

7278

7379
extern struct rb_root key_serial_tree;

security/keys/key.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ DEFINE_SPINLOCK(key_serial_lock);
2727
struct rb_root key_user_tree; /* tree of quota records indexed by UID */
2828
DEFINE_SPINLOCK(key_user_lock);
2929

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+
3035
static LIST_HEAD(key_types_list);
3136
static DECLARE_RWSEM(key_types_sem);
3237

@@ -236,11 +241,16 @@ struct key *key_alloc(struct key_type *type, const char *desc,
236241
/* check that the user's quota permits allocation of another key and
237242
* its description */
238243
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+
239249
spin_lock(&user->lock);
240250
if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
241-
if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
242-
user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
243-
)
251+
if (user->qnkeys + 1 >= maxkeys ||
252+
user->qnbytes + quotalen >= maxbytes ||
253+
user->qnbytes + quotalen < user->qnbytes)
244254
goto no_quota;
245255
}
246256

@@ -345,11 +355,14 @@ int key_payload_reserve(struct key *key, size_t datalen)
345355

346356
/* contemplate the quota adjustment */
347357
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+
348361
spin_lock(&key->user->lock);
349362

350363
if (delta > 0 &&
351-
key->user->qnbytes + delta > KEYQUOTA_MAX_BYTES
352-
) {
364+
(key->user->qnbytes + delta >= maxbytes ||
365+
key->user->qnbytes + delta < key->user->qnbytes)) {
353366
ret = -EDQUOT;
354367
}
355368
else {

security/keys/keyctl.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,10 +731,16 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
731731

732732
/* transfer the quota burden to the new user */
733733
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+
734739
spin_lock(&newowner->lock);
735-
if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
736-
newowner->qnbytes + key->quotalen >=
737-
KEYQUOTA_MAX_BYTES)
740+
if (newowner->qnkeys + 1 >= maxkeys ||
741+
newowner->qnbytes + key->quotalen >= maxbytes ||
742+
newowner->qnbytes + key->quotalen <
743+
newowner->qnbytes)
738744
goto quota_overrun;
739745

740746
newowner->qnkeys++;

security/keys/proc.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,20 @@ static int proc_key_users_show(struct seq_file *m, void *v)
242242
{
243243
struct rb_node *_p = v;
244244
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;
245249

246250
seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
247251
user->uid,
248252
atomic_read(&user->usage),
249253
atomic_read(&user->nkeys),
250254
atomic_read(&user->nikeys),
251255
user->qnkeys,
252-
KEYQUOTA_MAX_KEYS,
256+
maxkeys,
253257
user->qnbytes,
254-
KEYQUOTA_MAX_BYTES
255-
);
258+
maxbytes);
256259

257260
return 0;
258261

security/keys/sysctl.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
};

0 commit comments

Comments
 (0)