aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorSerge E. Hallyn <serue@us.ibm.com>2008-04-29 04:00:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:10 -0400
commit29486df325e1fe6e1764afcb19e3370804c2b002 (patch)
treed69a96bb829940f3ae5171fde481edb20a9e468a /security
parent28fd5dfc12bde391981dfdcf20755952b6e916af (diff)
cgroups: introduce cft->read_seq()
Introduce a read_seq() helper in cftype, which uses seq_file to print out lists. Use it in the devices cgroup. Also split devices.allow into two files, so now devices.deny and devices.allow are the ones to use to manipulate the whitelist, while devices.list outputs the cgroup's current whitelist. Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Acked-by: Paul Menage <menage@google.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security')
-rw-r--r--security/device_cgroup.c74
1 files changed, 23 insertions, 51 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 4237b19e8fb3..4ea583689eec 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -9,6 +9,7 @@
9#include <linux/ctype.h> 9#include <linux/ctype.h>
10#include <linux/list.h> 10#include <linux/list.h>
11#include <linux/uaccess.h> 11#include <linux/uaccess.h>
12#include <linux/seq_file.h>
12 13
13#define ACC_MKNOD 1 14#define ACC_MKNOD 1
14#define ACC_READ 2 15#define ACC_READ 2
@@ -201,11 +202,15 @@ static void devcgroup_destroy(struct cgroup_subsys *ss,
201 202
202#define DEVCG_ALLOW 1 203#define DEVCG_ALLOW 1
203#define DEVCG_DENY 2 204#define DEVCG_DENY 2
205#define DEVCG_LIST 3
206
207#define MAJMINLEN 10
208#define ACCLEN 4
204 209
205static void set_access(char *acc, short access) 210static void set_access(char *acc, short access)
206{ 211{
207 int idx = 0; 212 int idx = 0;
208 memset(acc, 0, 4); 213 memset(acc, 0, ACCLEN);
209 if (access & ACC_READ) 214 if (access & ACC_READ)
210 acc[idx++] = 'r'; 215 acc[idx++] = 'r';
211 if (access & ACC_WRITE) 216 if (access & ACC_WRITE)
@@ -225,70 +230,33 @@ static char type_to_char(short type)
225 return 'X'; 230 return 'X';
226} 231}
227 232
228static void set_majmin(char *str, int len, unsigned m) 233static void set_majmin(char *str, unsigned m)
229{ 234{
230 memset(str, 0, len); 235 memset(str, 0, MAJMINLEN);
231 if (m == ~0) 236 if (m == ~0)
232 sprintf(str, "*"); 237 sprintf(str, "*");
233 else 238 else
234 snprintf(str, len, "%d", m); 239 snprintf(str, MAJMINLEN, "%d", m);
235} 240}
236 241
237static char *print_whitelist(struct dev_cgroup *devcgroup, int *len) 242static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
243 struct seq_file *m)
238{ 244{
239 char *buf, *s, acc[4]; 245 struct dev_cgroup *devcgroup = cgroup_to_devcgroup(cgroup);
240 struct dev_whitelist_item *wh; 246 struct dev_whitelist_item *wh;
241 int ret; 247 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
242 int count = 0;
243 char maj[10], min[10];
244
245 buf = kmalloc(4096, GFP_KERNEL);
246 if (!buf)
247 return ERR_PTR(-ENOMEM);
248 s = buf;
249 *s = '\0';
250 *len = 0;
251 248
252 spin_lock(&devcgroup->lock); 249 spin_lock(&devcgroup->lock);
253 list_for_each_entry(wh, &devcgroup->whitelist, list) { 250 list_for_each_entry(wh, &devcgroup->whitelist, list) {
254 set_access(acc, wh->access); 251 set_access(acc, wh->access);
255 set_majmin(maj, 10, wh->major); 252 set_majmin(maj, wh->major);
256 set_majmin(min, 10, wh->minor); 253 set_majmin(min, wh->minor);
257 ret = snprintf(s, 4095-(s-buf), "%c %s:%s %s\n", 254 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
258 type_to_char(wh->type), maj, min, acc); 255 maj, min, acc);
259 if (s+ret >= buf+4095) {
260 kfree(buf);
261 buf = ERR_PTR(-ENOMEM);
262 break;
263 }
264 s += ret;
265 *len += ret;
266 count++;
267 } 256 }
268 spin_unlock(&devcgroup->lock); 257 spin_unlock(&devcgroup->lock);
269 258
270 return buf; 259 return 0;
271}
272
273static ssize_t devcgroup_access_read(struct cgroup *cgroup,
274 struct cftype *cft, struct file *file,
275 char __user *userbuf, size_t nbytes, loff_t *ppos)
276{
277 struct dev_cgroup *devcgroup = cgroup_to_devcgroup(cgroup);
278 int filetype = cft->private;
279 char *buffer;
280 int uninitialized_var(len);
281 int retval;
282
283 if (filetype != DEVCG_ALLOW)
284 return -EINVAL;
285 buffer = print_whitelist(devcgroup, &len);
286 if (IS_ERR(buffer))
287 return PTR_ERR(buffer);
288
289 retval = simple_read_from_buffer(userbuf, nbytes, ppos, buffer, len);
290 kfree(buffer);
291 return retval;
292} 260}
293 261
294/* 262/*
@@ -501,7 +469,6 @@ out1:
501static struct cftype dev_cgroup_files[] = { 469static struct cftype dev_cgroup_files[] = {
502 { 470 {
503 .name = "allow", 471 .name = "allow",
504 .read = devcgroup_access_read,
505 .write = devcgroup_access_write, 472 .write = devcgroup_access_write,
506 .private = DEVCG_ALLOW, 473 .private = DEVCG_ALLOW,
507 }, 474 },
@@ -510,6 +477,11 @@ static struct cftype dev_cgroup_files[] = {
510 .write = devcgroup_access_write, 477 .write = devcgroup_access_write,
511 .private = DEVCG_DENY, 478 .private = DEVCG_DENY,
512 }, 479 },
480 {
481 .name = "list",
482 .read_seq_string = devcgroup_seq_read,
483 .private = DEVCG_LIST,
484 },
513}; 485};
514 486
515static int devcgroup_populate(struct cgroup_subsys *ss, 487static int devcgroup_populate(struct cgroup_subsys *ss,