diff options
author | James Morris <jmorris@namei.org> | 2008-11-05 18:12:34 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-05 18:12:34 -0500 |
commit | e21e696edb498c7f7eed42ba3096f6bbe13927b6 (patch) | |
tree | 73b0bc28e45b0268f05c4b384a17bfb2140a73bc /security | |
parent | 2f99db28af90957271a6448479c3e492ccf7c697 (diff) | |
parent | 75fa67706cce5272bcfc51ed646f2da21f3bdb6e (diff) |
Merge branch 'master' into next
Diffstat (limited to 'security')
-rw-r--r-- | security/commoncap.c | 6 | ||||
-rw-r--r-- | security/device_cgroup.c | 46 | ||||
-rw-r--r-- | security/inode.c | 3 | ||||
-rw-r--r-- | security/security.c | 9 | ||||
-rw-r--r-- | security/selinux/hooks.c | 22 |
5 files changed, 30 insertions, 56 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index 399bfdb9e2da..3976613db829 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -279,10 +279,10 @@ static int get_file_caps(struct linux_binprm *bprm) | |||
279 | struct vfs_cap_data vcaps; | 279 | struct vfs_cap_data vcaps; |
280 | struct inode *inode; | 280 | struct inode *inode; |
281 | 281 | ||
282 | if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { | 282 | bprm_clear_caps(bprm); |
283 | bprm_clear_caps(bprm); | 283 | |
284 | if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) | ||
284 | return 0; | 285 | return 0; |
285 | } | ||
286 | 286 | ||
287 | dentry = dget(bprm->file->f_dentry); | 287 | dentry = dget(bprm->file->f_dentry); |
288 | inode = dentry->d_inode; | 288 | inode = dentry->d_inode; |
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/inode.c b/security/inode.c index ca4958ebad8d..efea5a605466 100644 --- a/security/inode.c +++ b/security/inode.c | |||
@@ -20,8 +20,7 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/namei.h> | 21 | #include <linux/namei.h> |
22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
23 | 23 | #include <linux/magic.h> | |
24 | #define SECURITYFS_MAGIC 0x73636673 | ||
25 | 24 | ||
26 | static struct vfsmount *mount; | 25 | static struct vfsmount *mount; |
27 | static int mount_count; | 26 | static int mount_count; |
diff --git a/security/security.c b/security/security.c index 255b08559b2b..c0acfa7177e5 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -198,14 +198,23 @@ int security_settime(struct timespec *ts, struct timezone *tz) | |||
198 | 198 | ||
199 | int security_vm_enough_memory(long pages) | 199 | int security_vm_enough_memory(long pages) |
200 | { | 200 | { |
201 | WARN_ON(current->mm == NULL); | ||
201 | return security_ops->vm_enough_memory(current->mm, pages); | 202 | return security_ops->vm_enough_memory(current->mm, pages); |
202 | } | 203 | } |
203 | 204 | ||
204 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) | 205 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) |
205 | { | 206 | { |
207 | WARN_ON(mm == NULL); | ||
206 | return security_ops->vm_enough_memory(mm, pages); | 208 | return security_ops->vm_enough_memory(mm, pages); |
207 | } | 209 | } |
208 | 210 | ||
211 | int security_vm_enough_memory_kern(long pages) | ||
212 | { | ||
213 | /* If current->mm is a kernel thread then we will pass NULL, | ||
214 | for this specific case that is fine */ | ||
215 | return security_ops->vm_enough_memory(current->mm, pages); | ||
216 | } | ||
217 | |||
209 | int security_bprm_alloc(struct linux_binprm *bprm) | 218 | int security_bprm_alloc(struct linux_binprm *bprm) |
210 | { | 219 | { |
211 | return security_ops->bprm_alloc_security(bprm); | 220 | return security_ops->bprm_alloc_security(bprm); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5f21a514f581..f71de5a64d0c 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" |
@@ -325,7 +326,7 @@ enum { | |||
325 | Opt_rootcontext = 4, | 326 | Opt_rootcontext = 4, |
326 | }; | 327 | }; |
327 | 328 | ||
328 | static match_table_t tokens = { | 329 | static const match_table_t tokens = { |
329 | {Opt_context, CONTEXT_STR "%s"}, | 330 | {Opt_context, CONTEXT_STR "%s"}, |
330 | {Opt_fscontext, FSCONTEXT_STR "%s"}, | 331 | {Opt_fscontext, FSCONTEXT_STR "%s"}, |
331 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, | 332 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, |
@@ -2123,26 +2124,27 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2123 | long j = -1; | 2124 | long j = -1; |
2124 | int drop_tty = 0; | 2125 | int drop_tty = 0; |
2125 | 2126 | ||
2126 | mutex_lock(&tty_mutex); | ||
2127 | tty = get_current_tty(); | 2127 | tty = get_current_tty(); |
2128 | if (tty) { | 2128 | if (tty) { |
2129 | file_list_lock(); | 2129 | file_list_lock(); |
2130 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); | 2130 | if (!list_empty(&tty->tty_files)) { |
2131 | if (file) { | 2131 | struct inode *inode; |
2132 | |||
2132 | /* Revalidate access to controlling tty. | 2133 | /* Revalidate access to controlling tty. |
2133 | Use inode_has_perm on the tty inode directly rather | 2134 | Use inode_has_perm on the tty inode directly rather |
2134 | than using file_has_perm, as this particular open | 2135 | than using file_has_perm, as this particular open |
2135 | file may belong to another process and we are only | 2136 | file may belong to another process and we are only |
2136 | interested in the inode-based check here. */ | 2137 | interested in the inode-based check here. */ |
2137 | struct inode *inode = file->f_path.dentry->d_inode; | 2138 | file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); |
2139 | inode = file->f_path.dentry->d_inode; | ||
2138 | if (inode_has_perm(current, inode, | 2140 | if (inode_has_perm(current, inode, |
2139 | FILE__READ | FILE__WRITE, NULL)) { | 2141 | FILE__READ | FILE__WRITE, NULL)) { |
2140 | drop_tty = 1; | 2142 | drop_tty = 1; |
2141 | } | 2143 | } |
2142 | } | 2144 | } |
2143 | file_list_unlock(); | 2145 | file_list_unlock(); |
2146 | tty_kref_put(tty); | ||
2144 | } | 2147 | } |
2145 | mutex_unlock(&tty_mutex); | ||
2146 | /* Reset controlling tty. */ | 2148 | /* Reset controlling tty. */ |
2147 | if (drop_tty) | 2149 | if (drop_tty) |
2148 | no_tty(); | 2150 | no_tty(); |
@@ -2326,13 +2328,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) | |||
2326 | initrlim = init_task.signal->rlim+i; | 2328 | initrlim = init_task.signal->rlim+i; |
2327 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2329 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2328 | } | 2330 | } |
2329 | if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { | 2331 | update_rlimit_cpu(rlim->rlim_cur); |
2330 | /* | ||
2331 | * This will cause RLIMIT_CPU calculations | ||
2332 | * to be refigured. | ||
2333 | */ | ||
2334 | current->it_prof_expires = jiffies_to_cputime(1); | ||
2335 | } | ||
2336 | } | 2332 | } |
2337 | 2333 | ||
2338 | /* Wake up the parent if it is waiting so that it can | 2334 | /* Wake up the parent if it is waiting so that it can |