aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2008-11-05 18:12:34 -0500
committerJames Morris <jmorris@namei.org>2008-11-05 18:12:34 -0500
commite21e696edb498c7f7eed42ba3096f6bbe13927b6 (patch)
tree73b0bc28e45b0268f05c4b384a17bfb2140a73bc /security
parent2f99db28af90957271a6448479c3e492ccf7c697 (diff)
parent75fa67706cce5272bcfc51ed646f2da21f3bdb6e (diff)
Merge branch 'master' into next
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c6
-rw-r--r--security/device_cgroup.c46
-rw-r--r--security/inode.c3
-rw-r--r--security/security.c9
-rw-r--r--security/selinux/hooks.c22
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
39struct dev_whitelist_item { 30struct dev_whitelist_item {
@@ -47,7 +38,6 @@ struct dev_whitelist_item {
47struct dev_cgroup { 38struct 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
53static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) 43static 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 */
112static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, 97static 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 */
154static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, 135static 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,
357static int devcgroup_update_access(struct dev_cgroup *devcgroup, 331static 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
439handle: 410handle:
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
26static struct vfsmount *mount; 25static struct vfsmount *mount;
27static int mount_count; 26static 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
199int security_vm_enough_memory(long pages) 199int 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
204int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) 205int 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
211int 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
209int security_bprm_alloc(struct linux_binprm *bprm) 218int 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
328static match_table_t tokens = { 329static 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