diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-24 06:48:46 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-24 06:48:46 -0400 |
commit | 8c82a17e9c924c0e9f13e75e4c2f6bca19a4b516 (patch) | |
tree | d535f46a917e14e90deccb29ad00aac016ad18dd /security | |
parent | 4ce72a2c063a7fa8e42a9435440ae3364115a58d (diff) | |
parent | 57f8f7b60db6f1ed2c6918ab9230c4623a9dbe37 (diff) |
Merge commit 'v2.6.28-rc1' into sched/urgent
Diffstat (limited to 'security')
-rw-r--r-- | security/device_cgroup.c | 46 | ||||
-rw-r--r-- | security/selinux/hooks.c | 9 |
2 files changed, 10 insertions, 45 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 46f23971f7e4..5ba78701adc3 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * dev_cgroup.c - device cgroup subsystem | 2 | * device_cgroup.c - device cgroup subsystem |
3 | * | 3 | * |
4 | * Copyright 2007 IBM Corp | 4 | * Copyright 2007 IBM Corp |
5 | */ | 5 | */ |
@@ -10,6 +10,7 @@ | |||
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 | #include <linux/seq_file.h> |
13 | #include <linux/rcupdate.h> | ||
13 | 14 | ||
14 | #define ACC_MKNOD 1 | 15 | #define ACC_MKNOD 1 |
15 | #define ACC_READ 2 | 16 | #define ACC_READ 2 |
@@ -22,18 +23,8 @@ | |||
22 | 23 | ||
23 | /* | 24 | /* |
24 | * whitelist locking rules: | 25 | * whitelist locking rules: |
25 | * cgroup_lock() cannot be taken under dev_cgroup->lock. | 26 | * hold cgroup_lock() for update/read. |
26 | * dev_cgroup->lock can be taken with or without cgroup_lock(). | 27 | * hold rcu_read_lock() for read. |
27 | * | ||
28 | * modifications always require cgroup_lock | ||
29 | * modifications to a list which is visible require the | ||
30 | * dev_cgroup->lock *and* cgroup_lock() | ||
31 | * walking the list requires dev_cgroup->lock or cgroup_lock(). | ||
32 | * | ||
33 | * reasoning: dev_whitelist_copy() needs to kmalloc, so needs | ||
34 | * a mutex, which the cgroup_lock() is. Since modifying | ||
35 | * a visible list requires both locks, either lock can be | ||
36 | * taken for walking the list. | ||
37 | */ | 28 | */ |
38 | 29 | ||
39 | struct dev_whitelist_item { | 30 | struct dev_whitelist_item { |
@@ -47,7 +38,6 @@ struct dev_whitelist_item { | |||
47 | struct dev_cgroup { | 38 | struct dev_cgroup { |
48 | struct cgroup_subsys_state css; | 39 | struct cgroup_subsys_state css; |
49 | struct list_head whitelist; | 40 | struct list_head whitelist; |
50 | spinlock_t lock; | ||
51 | }; | 41 | }; |
52 | 42 | ||
53 | static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) | 43 | static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) |
@@ -84,13 +74,9 @@ static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig) | |||
84 | struct dev_whitelist_item *wh, *tmp, *new; | 74 | struct dev_whitelist_item *wh, *tmp, *new; |
85 | 75 | ||
86 | list_for_each_entry(wh, orig, list) { | 76 | list_for_each_entry(wh, orig, list) { |
87 | new = kmalloc(sizeof(*wh), GFP_KERNEL); | 77 | new = kmemdup(wh, sizeof(*wh), GFP_KERNEL); |
88 | if (!new) | 78 | if (!new) |
89 | goto free_and_exit; | 79 | goto free_and_exit; |
90 | new->major = wh->major; | ||
91 | new->minor = wh->minor; | ||
92 | new->type = wh->type; | ||
93 | new->access = wh->access; | ||
94 | list_add_tail(&new->list, dest); | 80 | list_add_tail(&new->list, dest); |
95 | } | 81 | } |
96 | 82 | ||
@@ -107,19 +93,16 @@ free_and_exit: | |||
107 | /* Stupid prototype - don't bother combining existing entries */ | 93 | /* Stupid prototype - don't bother combining existing entries */ |
108 | /* | 94 | /* |
109 | * called under cgroup_lock() | 95 | * called under cgroup_lock() |
110 | * since the list is visible to other tasks, we need the spinlock also | ||
111 | */ | 96 | */ |
112 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | 97 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, |
113 | struct dev_whitelist_item *wh) | 98 | struct dev_whitelist_item *wh) |
114 | { | 99 | { |
115 | struct dev_whitelist_item *whcopy, *walk; | 100 | struct dev_whitelist_item *whcopy, *walk; |
116 | 101 | ||
117 | whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL); | 102 | whcopy = kmemdup(wh, sizeof(*wh), GFP_KERNEL); |
118 | if (!whcopy) | 103 | if (!whcopy) |
119 | return -ENOMEM; | 104 | return -ENOMEM; |
120 | 105 | ||
121 | memcpy(whcopy, wh, sizeof(*whcopy)); | ||
122 | spin_lock(&dev_cgroup->lock); | ||
123 | list_for_each_entry(walk, &dev_cgroup->whitelist, list) { | 106 | list_for_each_entry(walk, &dev_cgroup->whitelist, list) { |
124 | if (walk->type != wh->type) | 107 | if (walk->type != wh->type) |
125 | continue; | 108 | continue; |
@@ -135,7 +118,6 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | |||
135 | 118 | ||
136 | if (whcopy != NULL) | 119 | if (whcopy != NULL) |
137 | list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist); | 120 | list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist); |
138 | spin_unlock(&dev_cgroup->lock); | ||
139 | return 0; | 121 | return 0; |
140 | } | 122 | } |
141 | 123 | ||
@@ -149,14 +131,12 @@ static void whitelist_item_free(struct rcu_head *rcu) | |||
149 | 131 | ||
150 | /* | 132 | /* |
151 | * called under cgroup_lock() | 133 | * called under cgroup_lock() |
152 | * since the list is visible to other tasks, we need the spinlock also | ||
153 | */ | 134 | */ |
154 | static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, | 135 | static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, |
155 | struct dev_whitelist_item *wh) | 136 | struct dev_whitelist_item *wh) |
156 | { | 137 | { |
157 | struct dev_whitelist_item *walk, *tmp; | 138 | struct dev_whitelist_item *walk, *tmp; |
158 | 139 | ||
159 | spin_lock(&dev_cgroup->lock); | ||
160 | list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) { | 140 | list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) { |
161 | if (walk->type == DEV_ALL) | 141 | if (walk->type == DEV_ALL) |
162 | goto remove; | 142 | goto remove; |
@@ -174,7 +154,6 @@ remove: | |||
174 | call_rcu(&walk->rcu, whitelist_item_free); | 154 | call_rcu(&walk->rcu, whitelist_item_free); |
175 | } | 155 | } |
176 | } | 156 | } |
177 | spin_unlock(&dev_cgroup->lock); | ||
178 | } | 157 | } |
179 | 158 | ||
180 | /* | 159 | /* |
@@ -214,7 +193,6 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss, | |||
214 | } | 193 | } |
215 | } | 194 | } |
216 | 195 | ||
217 | spin_lock_init(&dev_cgroup->lock); | ||
218 | return &dev_cgroup->css; | 196 | return &dev_cgroup->css; |
219 | } | 197 | } |
220 | 198 | ||
@@ -330,15 +308,11 @@ static int parent_has_perm(struct dev_cgroup *childcg, | |||
330 | { | 308 | { |
331 | struct cgroup *pcg = childcg->css.cgroup->parent; | 309 | struct cgroup *pcg = childcg->css.cgroup->parent; |
332 | struct dev_cgroup *parent; | 310 | struct dev_cgroup *parent; |
333 | int ret; | ||
334 | 311 | ||
335 | if (!pcg) | 312 | if (!pcg) |
336 | return 1; | 313 | return 1; |
337 | parent = cgroup_to_devcgroup(pcg); | 314 | parent = cgroup_to_devcgroup(pcg); |
338 | spin_lock(&parent->lock); | 315 | return may_access_whitelist(parent, wh); |
339 | ret = may_access_whitelist(parent, wh); | ||
340 | spin_unlock(&parent->lock); | ||
341 | return ret; | ||
342 | } | 316 | } |
343 | 317 | ||
344 | /* | 318 | /* |
@@ -357,17 +331,14 @@ static int parent_has_perm(struct dev_cgroup *childcg, | |||
357 | static int devcgroup_update_access(struct dev_cgroup *devcgroup, | 331 | static int devcgroup_update_access(struct dev_cgroup *devcgroup, |
358 | int filetype, const char *buffer) | 332 | int filetype, const char *buffer) |
359 | { | 333 | { |
360 | struct dev_cgroup *cur_devcgroup; | ||
361 | const char *b; | 334 | const char *b; |
362 | char *endp; | 335 | char *endp; |
363 | int retval = 0, count; | 336 | int count; |
364 | struct dev_whitelist_item wh; | 337 | struct dev_whitelist_item wh; |
365 | 338 | ||
366 | if (!capable(CAP_SYS_ADMIN)) | 339 | if (!capable(CAP_SYS_ADMIN)) |
367 | return -EPERM; | 340 | return -EPERM; |
368 | 341 | ||
369 | cur_devcgroup = task_devcgroup(current); | ||
370 | |||
371 | memset(&wh, 0, sizeof(wh)); | 342 | memset(&wh, 0, sizeof(wh)); |
372 | b = buffer; | 343 | b = buffer; |
373 | 344 | ||
@@ -437,7 +408,6 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, | |||
437 | } | 408 | } |
438 | 409 | ||
439 | handle: | 410 | handle: |
440 | retval = 0; | ||
441 | switch (filetype) { | 411 | switch (filetype) { |
442 | case DEVCG_ALLOW: | 412 | case DEVCG_ALLOW: |
443 | if (!parent_has_perm(devcgroup, &wh)) | 413 | if (!parent_has_perm(devcgroup, &wh)) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 576e51199079..3e3fde7c1d2b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -75,6 +75,7 @@ | |||
75 | #include <linux/string.h> | 75 | #include <linux/string.h> |
76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
78 | #include <linux/posix-timers.h> | ||
78 | 79 | ||
79 | #include "avc.h" | 80 | #include "avc.h" |
80 | #include "objsec.h" | 81 | #include "objsec.h" |
@@ -2322,13 +2323,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) | |||
2322 | initrlim = init_task.signal->rlim+i; | 2323 | initrlim = init_task.signal->rlim+i; |
2323 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2324 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2324 | } | 2325 | } |
2325 | if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { | 2326 | update_rlimit_cpu(rlim->rlim_cur); |
2326 | /* | ||
2327 | * This will cause RLIMIT_CPU calculations | ||
2328 | * to be refigured. | ||
2329 | */ | ||
2330 | current->it_prof_expires = jiffies_to_cputime(1); | ||
2331 | } | ||
2332 | } | 2327 | } |
2333 | 2328 | ||
2334 | /* Wake up the parent if it is waiting so that it can | 2329 | /* Wake up the parent if it is waiting so that it can |