aboutsummaryrefslogtreecommitdiffstats
path: root/security/device_cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/device_cgroup.c')
-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,