aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-09-22 07:08:57 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-22 07:08:57 -0400
commit0b88641f1bafdbd087d5e63987a30cc0eadd63b9 (patch)
tree81dcf756db373444140bb2623584710c628e3048 /security
parentfbdbf709938d155c719c76b9894d28342632c797 (diff)
parent72d31053f62c4bc464c2783974926969614a8649 (diff)
Merge commit 'v2.6.27-rc7' into x86/debug
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig3
-rw-r--r--security/capability.c6
-rw-r--r--security/commoncap.c132
-rw-r--r--security/device_cgroup.c174
-rw-r--r--security/root_plug.c3
-rw-r--r--security/security.c15
-rw-r--r--security/selinux/hooks.c85
-rw-r--r--security/selinux/ss/services.c6
-rw-r--r--security/smack/smack_lsm.c52
9 files changed, 242 insertions, 234 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 62ed4717d334..559293922a47 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -74,8 +74,7 @@ config SECURITY_NETWORK_XFRM
74 If you are unsure how to answer this question, answer N. 74 If you are unsure how to answer this question, answer N.
75 75
76config SECURITY_FILE_CAPABILITIES 76config SECURITY_FILE_CAPABILITIES
77 bool "File POSIX Capabilities (EXPERIMENTAL)" 77 bool "File POSIX Capabilities"
78 depends on EXPERIMENTAL
79 default n 78 default n
80 help 79 help
81 This enables filesystem capabilities, allowing you to give 80 This enables filesystem capabilities, allowing you to give
diff --git a/security/capability.c b/security/capability.c
index 5b01c0b02422..245874819036 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -211,8 +211,7 @@ static int cap_inode_follow_link(struct dentry *dentry,
211 return 0; 211 return 0;
212} 212}
213 213
214static int cap_inode_permission(struct inode *inode, int mask, 214static int cap_inode_permission(struct inode *inode, int mask)
215 struct nameidata *nd)
216{ 215{
217 return 0; 216 return 0;
218} 217}
@@ -812,7 +811,8 @@ struct security_operations default_security_ops = {
812 811
813void security_fixup_ops(struct security_operations *ops) 812void security_fixup_ops(struct security_operations *ops)
814{ 813{
815 set_to_cap_if_null(ops, ptrace); 814 set_to_cap_if_null(ops, ptrace_may_access);
815 set_to_cap_if_null(ops, ptrace_traceme);
816 set_to_cap_if_null(ops, capget); 816 set_to_cap_if_null(ops, capget);
817 set_to_cap_if_null(ops, capset_check); 817 set_to_cap_if_null(ops, capset_check);
818 set_to_cap_if_null(ops, capset_set); 818 set_to_cap_if_null(ops, capset_set);
diff --git a/security/commoncap.c b/security/commoncap.c
index 0b6537a3672d..e4c4b3fc0c04 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -63,14 +63,24 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
63 return 0; 63 return 0;
64} 64}
65 65
66int cap_ptrace (struct task_struct *parent, struct task_struct *child, 66int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
67 unsigned int mode)
68{ 67{
69 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ 68 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
70 if (!cap_issubset(child->cap_permitted, parent->cap_permitted) && 69 if (cap_issubset(child->cap_permitted, current->cap_permitted))
71 !__capable(parent, CAP_SYS_PTRACE)) 70 return 0;
72 return -EPERM; 71 if (capable(CAP_SYS_PTRACE))
73 return 0; 72 return 0;
73 return -EPERM;
74}
75
76int cap_ptrace_traceme(struct task_struct *parent)
77{
78 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
79 if (cap_issubset(current->cap_permitted, parent->cap_permitted))
80 return 0;
81 if (has_capability(parent, CAP_SYS_PTRACE))
82 return 0;
83 return -EPERM;
74} 84}
75 85
76int cap_capget (struct task_struct *target, kernel_cap_t *effective, 86int cap_capget (struct task_struct *target, kernel_cap_t *effective,
@@ -162,8 +172,7 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
162 172
163static inline void bprm_clear_caps(struct linux_binprm *bprm) 173static inline void bprm_clear_caps(struct linux_binprm *bprm)
164{ 174{
165 cap_clear(bprm->cap_inheritable); 175 cap_clear(bprm->cap_post_exec_permitted);
166 cap_clear(bprm->cap_permitted);
167 bprm->cap_effective = false; 176 bprm->cap_effective = false;
168} 177}
169 178
@@ -198,6 +207,7 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
198{ 207{
199 __u32 magic_etc; 208 __u32 magic_etc;
200 unsigned tocopy, i; 209 unsigned tocopy, i;
210 int ret;
201 211
202 if (size < sizeof(magic_etc)) 212 if (size < sizeof(magic_etc))
203 return -EINVAL; 213 return -EINVAL;
@@ -225,19 +235,40 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
225 bprm->cap_effective = false; 235 bprm->cap_effective = false;
226 } 236 }
227 237
228 for (i = 0; i < tocopy; ++i) { 238 ret = 0;
229 bprm->cap_permitted.cap[i] = 239
230 le32_to_cpu(caps->data[i].permitted); 240 CAP_FOR_EACH_U32(i) {
231 bprm->cap_inheritable.cap[i] = 241 __u32 value_cpu;
232 le32_to_cpu(caps->data[i].inheritable); 242
233 } 243 if (i >= tocopy) {
234 while (i < VFS_CAP_U32) { 244 /*
235 bprm->cap_permitted.cap[i] = 0; 245 * Legacy capability sets have no upper bits
236 bprm->cap_inheritable.cap[i] = 0; 246 */
237 i++; 247 bprm->cap_post_exec_permitted.cap[i] = 0;
248 continue;
249 }
250 /*
251 * pP' = (X & fP) | (pI & fI)
252 */
253 value_cpu = le32_to_cpu(caps->data[i].permitted);
254 bprm->cap_post_exec_permitted.cap[i] =
255 (current->cap_bset.cap[i] & value_cpu) |
256 (current->cap_inheritable.cap[i] &
257 le32_to_cpu(caps->data[i].inheritable));
258 if (value_cpu & ~bprm->cap_post_exec_permitted.cap[i]) {
259 /*
260 * insufficient to execute correctly
261 */
262 ret = -EPERM;
263 }
238 } 264 }
239 265
240 return 0; 266 /*
267 * For legacy apps, with no internal support for recognizing they
268 * do not have enough capabilities, we return an error if they are
269 * missing some "forced" (aka file-permitted) capabilities.
270 */
271 return bprm->cap_effective ? ret : 0;
241} 272}
242 273
243/* Locate any VFS capabilities: */ 274/* Locate any VFS capabilities: */
@@ -269,9 +300,9 @@ static int get_file_caps(struct linux_binprm *bprm)
269 goto out; 300 goto out;
270 301
271 rc = cap_from_disk(&vcaps, bprm, rc); 302 rc = cap_from_disk(&vcaps, bprm, rc);
272 if (rc) 303 if (rc == -EINVAL)
273 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", 304 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
274 __func__, rc, bprm->filename); 305 __func__, rc, bprm->filename);
275 306
276out: 307out:
277 dput(dentry); 308 dput(dentry);
@@ -304,25 +335,24 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
304 int ret; 335 int ret;
305 336
306 ret = get_file_caps(bprm); 337 ret = get_file_caps(bprm);
307 if (ret)
308 printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
309 __func__, ret, bprm->filename);
310
311 /* To support inheritance of root-permissions and suid-root
312 * executables under compatibility mode, we raise all three
313 * capability sets for the file.
314 *
315 * If only the real uid is 0, we only raise the inheritable
316 * and permitted sets of the executable file.
317 */
318 338
319 if (!issecure (SECURE_NOROOT)) { 339 if (!issecure(SECURE_NOROOT)) {
340 /*
341 * To support inheritance of root-permissions and suid-root
342 * executables under compatibility mode, we override the
343 * capability sets for the file.
344 *
345 * If only the real uid is 0, we do not set the effective
346 * bit.
347 */
320 if (bprm->e_uid == 0 || current->uid == 0) { 348 if (bprm->e_uid == 0 || current->uid == 0) {
321 cap_set_full (bprm->cap_inheritable); 349 /* pP' = (cap_bset & ~0) | (pI & ~0) */
322 cap_set_full (bprm->cap_permitted); 350 bprm->cap_post_exec_permitted = cap_combine(
351 current->cap_bset, current->cap_inheritable
352 );
353 bprm->cap_effective = (bprm->e_uid == 0);
354 ret = 0;
323 } 355 }
324 if (bprm->e_uid == 0)
325 bprm->cap_effective = true;
326 } 356 }
327 357
328 return ret; 358 return ret;
@@ -330,17 +360,9 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
330 360
331void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 361void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
332{ 362{
333 /* Derived from fs/exec.c:compute_creds. */
334 kernel_cap_t new_permitted, working;
335
336 new_permitted = cap_intersect(bprm->cap_permitted,
337 current->cap_bset);
338 working = cap_intersect(bprm->cap_inheritable,
339 current->cap_inheritable);
340 new_permitted = cap_combine(new_permitted, working);
341
342 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 363 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
343 !cap_issubset (new_permitted, current->cap_permitted)) { 364 !cap_issubset(bprm->cap_post_exec_permitted,
365 current->cap_permitted)) {
344 set_dumpable(current->mm, suid_dumpable); 366 set_dumpable(current->mm, suid_dumpable);
345 current->pdeath_signal = 0; 367 current->pdeath_signal = 0;
346 368
@@ -350,9 +372,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
350 bprm->e_gid = current->gid; 372 bprm->e_gid = current->gid;
351 } 373 }
352 if (cap_limit_ptraced_target()) { 374 if (cap_limit_ptraced_target()) {
353 new_permitted = 375 bprm->cap_post_exec_permitted = cap_intersect(
354 cap_intersect(new_permitted, 376 bprm->cap_post_exec_permitted,
355 current->cap_permitted); 377 current->cap_permitted);
356 } 378 }
357 } 379 }
358 } 380 }
@@ -364,9 +386,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
364 * in the init_task struct. Thus we skip the usual 386 * in the init_task struct. Thus we skip the usual
365 * capability rules */ 387 * capability rules */
366 if (!is_global_init(current)) { 388 if (!is_global_init(current)) {
367 current->cap_permitted = new_permitted; 389 current->cap_permitted = bprm->cap_post_exec_permitted;
368 if (bprm->cap_effective) 390 if (bprm->cap_effective)
369 current->cap_effective = new_permitted; 391 current->cap_effective = bprm->cap_post_exec_permitted;
370 else 392 else
371 cap_clear(current->cap_effective); 393 cap_clear(current->cap_effective);
372 } 394 }
@@ -381,9 +403,7 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
381 if (current->uid != 0) { 403 if (current->uid != 0) {
382 if (bprm->cap_effective) 404 if (bprm->cap_effective)
383 return 1; 405 return 1;
384 if (!cap_isclear(bprm->cap_permitted)) 406 if (!cap_isclear(bprm->cap_post_exec_permitted))
385 return 1;
386 if (!cap_isclear(bprm->cap_inheritable))
387 return 1; 407 return 1;
388 } 408 }
389 409
@@ -524,7 +544,7 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
524static inline int cap_safe_nice(struct task_struct *p) 544static inline int cap_safe_nice(struct task_struct *p)
525{ 545{
526 if (!cap_issubset(p->cap_permitted, current->cap_permitted) && 546 if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
527 !__capable(current, CAP_SYS_NICE)) 547 !capable(CAP_SYS_NICE))
528 return -EPERM; 548 return -EPERM;
529 return 0; 549 return 0;
530} 550}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index ddd92cec78ed..46f23971f7e4 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -41,6 +41,7 @@ struct dev_whitelist_item {
41 short type; 41 short type;
42 short access; 42 short access;
43 struct list_head list; 43 struct list_head list;
44 struct rcu_head rcu;
44}; 45};
45 46
46struct dev_cgroup { 47struct dev_cgroup {
@@ -59,6 +60,11 @@ static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
59 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); 60 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
60} 61}
61 62
63static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
64{
65 return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
66}
67
62struct cgroup_subsys devices_subsys; 68struct cgroup_subsys devices_subsys;
63 69
64static int devcgroup_can_attach(struct cgroup_subsys *ss, 70static int devcgroup_can_attach(struct cgroup_subsys *ss,
@@ -128,11 +134,19 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
128 } 134 }
129 135
130 if (whcopy != NULL) 136 if (whcopy != NULL)
131 list_add_tail(&whcopy->list, &dev_cgroup->whitelist); 137 list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
132 spin_unlock(&dev_cgroup->lock); 138 spin_unlock(&dev_cgroup->lock);
133 return 0; 139 return 0;
134} 140}
135 141
142static void whitelist_item_free(struct rcu_head *rcu)
143{
144 struct dev_whitelist_item *item;
145
146 item = container_of(rcu, struct dev_whitelist_item, rcu);
147 kfree(item);
148}
149
136/* 150/*
137 * called under cgroup_lock() 151 * called under cgroup_lock()
138 * since the list is visible to other tasks, we need the spinlock also 152 * since the list is visible to other tasks, we need the spinlock also
@@ -156,8 +170,8 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
156remove: 170remove:
157 walk->access &= ~wh->access; 171 walk->access &= ~wh->access;
158 if (!walk->access) { 172 if (!walk->access) {
159 list_del(&walk->list); 173 list_del_rcu(&walk->list);
160 kfree(walk); 174 call_rcu(&walk->rcu, whitelist_item_free);
161 } 175 }
162 } 176 }
163 spin_unlock(&dev_cgroup->lock); 177 spin_unlock(&dev_cgroup->lock);
@@ -188,7 +202,7 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
188 } 202 }
189 wh->minor = wh->major = ~0; 203 wh->minor = wh->major = ~0;
190 wh->type = DEV_ALL; 204 wh->type = DEV_ALL;
191 wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE; 205 wh->access = ACC_MASK;
192 list_add(&wh->list, &dev_cgroup->whitelist); 206 list_add(&wh->list, &dev_cgroup->whitelist);
193 } else { 207 } else {
194 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); 208 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
@@ -250,11 +264,10 @@ static char type_to_char(short type)
250 264
251static void set_majmin(char *str, unsigned m) 265static void set_majmin(char *str, unsigned m)
252{ 266{
253 memset(str, 0, MAJMINLEN);
254 if (m == ~0) 267 if (m == ~0)
255 sprintf(str, "*"); 268 strcpy(str, "*");
256 else 269 else
257 snprintf(str, MAJMINLEN, "%u", m); 270 sprintf(str, "%u", m);
258} 271}
259 272
260static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, 273static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
@@ -264,15 +277,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
264 struct dev_whitelist_item *wh; 277 struct dev_whitelist_item *wh;
265 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; 278 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
266 279
267 spin_lock(&devcgroup->lock); 280 rcu_read_lock();
268 list_for_each_entry(wh, &devcgroup->whitelist, list) { 281 list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
269 set_access(acc, wh->access); 282 set_access(acc, wh->access);
270 set_majmin(maj, wh->major); 283 set_majmin(maj, wh->major);
271 set_majmin(min, wh->minor); 284 set_majmin(min, wh->minor);
272 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type), 285 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
273 maj, min, acc); 286 maj, min, acc);
274 } 287 }
275 spin_unlock(&devcgroup->lock); 288 rcu_read_unlock();
276 289
277 return 0; 290 return 0;
278} 291}
@@ -312,10 +325,10 @@ static int may_access_whitelist(struct dev_cgroup *c,
312 * when adding a new allow rule to a device whitelist, the rule 325 * when adding a new allow rule to a device whitelist, the rule
313 * must be allowed in the parent device 326 * must be allowed in the parent device
314 */ 327 */
315static int parent_has_perm(struct cgroup *childcg, 328static int parent_has_perm(struct dev_cgroup *childcg,
316 struct dev_whitelist_item *wh) 329 struct dev_whitelist_item *wh)
317{ 330{
318 struct cgroup *pcg = childcg->parent; 331 struct cgroup *pcg = childcg->css.cgroup->parent;
319 struct dev_cgroup *parent; 332 struct dev_cgroup *parent;
320 int ret; 333 int ret;
321 334
@@ -341,39 +354,19 @@ static int parent_has_perm(struct cgroup *childcg,
341 * new access is only allowed if you're in the top-level cgroup, or your 354 * new access is only allowed if you're in the top-level cgroup, or your
342 * parent cgroup has the access you're asking for. 355 * parent cgroup has the access you're asking for.
343 */ 356 */
344static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, 357static int devcgroup_update_access(struct dev_cgroup *devcgroup,
345 struct file *file, const char __user *userbuf, 358 int filetype, const char *buffer)
346 size_t nbytes, loff_t *ppos)
347{ 359{
348 struct cgroup *cur_cgroup; 360 struct dev_cgroup *cur_devcgroup;
349 struct dev_cgroup *devcgroup, *cur_devcgroup; 361 const char *b;
350 int filetype = cft->private; 362 char *endp;
351 char *buffer, *b;
352 int retval = 0, count; 363 int retval = 0, count;
353 struct dev_whitelist_item wh; 364 struct dev_whitelist_item wh;
354 365
355 if (!capable(CAP_SYS_ADMIN)) 366 if (!capable(CAP_SYS_ADMIN))
356 return -EPERM; 367 return -EPERM;
357 368
358 devcgroup = cgroup_to_devcgroup(cgroup); 369 cur_devcgroup = task_devcgroup(current);
359 cur_cgroup = task_cgroup(current, devices_subsys.subsys_id);
360 cur_devcgroup = cgroup_to_devcgroup(cur_cgroup);
361
362 buffer = kmalloc(nbytes+1, GFP_KERNEL);
363 if (!buffer)
364 return -ENOMEM;
365
366 if (copy_from_user(buffer, userbuf, nbytes)) {
367 retval = -EFAULT;
368 goto out1;
369 }
370 buffer[nbytes] = 0; /* nul-terminate */
371
372 cgroup_lock();
373 if (cgroup_is_removed(cgroup)) {
374 retval = -ENODEV;
375 goto out2;
376 }
377 370
378 memset(&wh, 0, sizeof(wh)); 371 memset(&wh, 0, sizeof(wh));
379 b = buffer; 372 b = buffer;
@@ -392,32 +385,23 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
392 wh.type = DEV_CHAR; 385 wh.type = DEV_CHAR;
393 break; 386 break;
394 default: 387 default:
395 retval = -EINVAL; 388 return -EINVAL;
396 goto out2;
397 } 389 }
398 b++; 390 b++;
399 if (!isspace(*b)) { 391 if (!isspace(*b))
400 retval = -EINVAL; 392 return -EINVAL;
401 goto out2;
402 }
403 b++; 393 b++;
404 if (*b == '*') { 394 if (*b == '*') {
405 wh.major = ~0; 395 wh.major = ~0;
406 b++; 396 b++;
407 } else if (isdigit(*b)) { 397 } else if (isdigit(*b)) {
408 wh.major = 0; 398 wh.major = simple_strtoul(b, &endp, 10);
409 while (isdigit(*b)) { 399 b = endp;
410 wh.major = wh.major*10+(*b-'0');
411 b++;
412 }
413 } else { 400 } else {
414 retval = -EINVAL; 401 return -EINVAL;
415 goto out2;
416 }
417 if (*b != ':') {
418 retval = -EINVAL;
419 goto out2;
420 } 402 }
403 if (*b != ':')
404 return -EINVAL;
421 b++; 405 b++;
422 406
423 /* read minor */ 407 /* read minor */
@@ -425,19 +409,13 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
425 wh.minor = ~0; 409 wh.minor = ~0;
426 b++; 410 b++;
427 } else if (isdigit(*b)) { 411 } else if (isdigit(*b)) {
428 wh.minor = 0; 412 wh.minor = simple_strtoul(b, &endp, 10);
429 while (isdigit(*b)) { 413 b = endp;
430 wh.minor = wh.minor*10+(*b-'0');
431 b++;
432 }
433 } else { 414 } else {
434 retval = -EINVAL; 415 return -EINVAL;
435 goto out2;
436 }
437 if (!isspace(*b)) {
438 retval = -EINVAL;
439 goto out2;
440 } 416 }
417 if (!isspace(*b))
418 return -EINVAL;
441 for (b++, count = 0; count < 3; count++, b++) { 419 for (b++, count = 0; count < 3; count++, b++) {
442 switch (*b) { 420 switch (*b) {
443 case 'r': 421 case 'r':
@@ -454,8 +432,7 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
454 count = 3; 432 count = 3;
455 break; 433 break;
456 default: 434 default:
457 retval = -EINVAL; 435 return -EINVAL;
458 goto out2;
459 } 436 }
460 } 437 }
461 438
@@ -463,38 +440,39 @@ handle:
463 retval = 0; 440 retval = 0;
464 switch (filetype) { 441 switch (filetype) {
465 case DEVCG_ALLOW: 442 case DEVCG_ALLOW:
466 if (!parent_has_perm(cgroup, &wh)) 443 if (!parent_has_perm(devcgroup, &wh))
467 retval = -EPERM; 444 return -EPERM;
468 else 445 return dev_whitelist_add(devcgroup, &wh);
469 retval = dev_whitelist_add(devcgroup, &wh);
470 break;
471 case DEVCG_DENY: 446 case DEVCG_DENY:
472 dev_whitelist_rm(devcgroup, &wh); 447 dev_whitelist_rm(devcgroup, &wh);
473 break; 448 break;
474 default: 449 default:
475 retval = -EINVAL; 450 return -EINVAL;
476 goto out2;
477 } 451 }
452 return 0;
453}
478 454
479 if (retval == 0) 455static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
480 retval = nbytes; 456 const char *buffer)
481 457{
482out2: 458 int retval;
459 if (!cgroup_lock_live_group(cgrp))
460 return -ENODEV;
461 retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
462 cft->private, buffer);
483 cgroup_unlock(); 463 cgroup_unlock();
484out1:
485 kfree(buffer);
486 return retval; 464 return retval;
487} 465}
488 466
489static struct cftype dev_cgroup_files[] = { 467static struct cftype dev_cgroup_files[] = {
490 { 468 {
491 .name = "allow", 469 .name = "allow",
492 .write = devcgroup_access_write, 470 .write_string = devcgroup_access_write,
493 .private = DEVCG_ALLOW, 471 .private = DEVCG_ALLOW,
494 }, 472 },
495 { 473 {
496 .name = "deny", 474 .name = "deny",
497 .write = devcgroup_access_write, 475 .write_string = devcgroup_access_write,
498 .private = DEVCG_DENY, 476 .private = DEVCG_DENY,
499 }, 477 },
500 { 478 {
@@ -530,13 +508,12 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
530 return 0; 508 return 0;
531 if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) 509 if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
532 return 0; 510 return 0;
533 dev_cgroup = css_to_devcgroup(task_subsys_state(current,
534 devices_subsys_id));
535 if (!dev_cgroup)
536 return 0;
537 511
538 spin_lock(&dev_cgroup->lock); 512 rcu_read_lock();
539 list_for_each_entry(wh, &dev_cgroup->whitelist, list) { 513
514 dev_cgroup = task_devcgroup(current);
515
516 list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
540 if (wh->type & DEV_ALL) 517 if (wh->type & DEV_ALL)
541 goto acc_check; 518 goto acc_check;
542 if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode)) 519 if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
@@ -552,10 +529,11 @@ acc_check:
552 continue; 529 continue;
553 if ((mask & MAY_READ) && !(wh->access & ACC_READ)) 530 if ((mask & MAY_READ) && !(wh->access & ACC_READ))
554 continue; 531 continue;
555 spin_unlock(&dev_cgroup->lock); 532 rcu_read_unlock();
556 return 0; 533 return 0;
557 } 534 }
558 spin_unlock(&dev_cgroup->lock); 535
536 rcu_read_unlock();
559 537
560 return -EPERM; 538 return -EPERM;
561} 539}
@@ -565,12 +543,10 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
565 struct dev_cgroup *dev_cgroup; 543 struct dev_cgroup *dev_cgroup;
566 struct dev_whitelist_item *wh; 544 struct dev_whitelist_item *wh;
567 545
568 dev_cgroup = css_to_devcgroup(task_subsys_state(current, 546 rcu_read_lock();
569 devices_subsys_id)); 547
570 if (!dev_cgroup) 548 dev_cgroup = task_devcgroup(current);
571 return 0;
572 549
573 spin_lock(&dev_cgroup->lock);
574 list_for_each_entry(wh, &dev_cgroup->whitelist, list) { 550 list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
575 if (wh->type & DEV_ALL) 551 if (wh->type & DEV_ALL)
576 goto acc_check; 552 goto acc_check;
@@ -585,9 +561,11 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
585acc_check: 561acc_check:
586 if (!(wh->access & ACC_MKNOD)) 562 if (!(wh->access & ACC_MKNOD))
587 continue; 563 continue;
588 spin_unlock(&dev_cgroup->lock); 564 rcu_read_unlock();
589 return 0; 565 return 0;
590 } 566 }
591 spin_unlock(&dev_cgroup->lock); 567
568 rcu_read_unlock();
569
592 return -EPERM; 570 return -EPERM;
593} 571}
diff --git a/security/root_plug.c b/security/root_plug.c
index be0ebec2580b..c3f68b5b372d 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -72,7 +72,8 @@ static int rootplug_bprm_check_security (struct linux_binprm *bprm)
72 72
73static struct security_operations rootplug_security_ops = { 73static struct security_operations rootplug_security_ops = {
74 /* Use the capability functions for some of the hooks */ 74 /* Use the capability functions for some of the hooks */
75 .ptrace = cap_ptrace, 75 .ptrace_may_access = cap_ptrace_may_access,
76 .ptrace_traceme = cap_ptrace_traceme,
76 .capget = cap_capget, 77 .capget = cap_capget,
77 .capset_check = cap_capset_check, 78 .capset_check = cap_capset_check,
78 .capset_set = cap_capset_set, 79 .capset_set = cap_capset_set,
diff --git a/security/security.c b/security/security.c
index 59f23b5918b3..3a4b4f55b33f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -127,10 +127,14 @@ int register_security(struct security_operations *ops)
127 127
128/* Security operations */ 128/* Security operations */
129 129
130int security_ptrace(struct task_struct *parent, struct task_struct *child, 130int security_ptrace_may_access(struct task_struct *child, unsigned int mode)
131 unsigned int mode)
132{ 131{
133 return security_ops->ptrace(parent, child, mode); 132 return security_ops->ptrace_may_access(child, mode);
133}
134
135int security_ptrace_traceme(struct task_struct *parent)
136{
137 return security_ops->ptrace_traceme(parent);
134} 138}
135 139
136int security_capget(struct task_struct *target, 140int security_capget(struct task_struct *target,
@@ -429,11 +433,11 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
429 return security_ops->inode_follow_link(dentry, nd); 433 return security_ops->inode_follow_link(dentry, nd);
430} 434}
431 435
432int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd) 436int security_inode_permission(struct inode *inode, int mask)
433{ 437{
434 if (unlikely(IS_PRIVATE(inode))) 438 if (unlikely(IS_PRIVATE(inode)))
435 return 0; 439 return 0;
436 return security_ops->inode_permission(inode, mask, nd); 440 return security_ops->inode_permission(inode, mask);
437} 441}
438 442
439int security_inode_setattr(struct dentry *dentry, struct iattr *attr) 443int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
@@ -442,6 +446,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
442 return 0; 446 return 0;
443 return security_ops->inode_setattr(dentry, attr); 447 return security_ops->inode_setattr(dentry, attr);
444} 448}
449EXPORT_SYMBOL_GPL(security_inode_setattr);
445 450
446int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) 451int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
447{ 452{
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 63f131fc42e4..03fc6a81ae32 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -25,7 +25,7 @@
25 25
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/kernel.h> 27#include <linux/kernel.h>
28#include <linux/ptrace.h> 28#include <linux/tracehook.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/security.h> 31#include <linux/security.h>
@@ -998,8 +998,12 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
998 int rc; 998 int rc;
999 999
1000 rc = selinux_get_mnt_opts(sb, &opts); 1000 rc = selinux_get_mnt_opts(sb, &opts);
1001 if (rc) 1001 if (rc) {
1002 /* before policy load we may get EINVAL, don't show anything */
1003 if (rc == -EINVAL)
1004 rc = 0;
1002 return rc; 1005 return rc;
1006 }
1003 1007
1004 selinux_write_opts(m, &opts); 1008 selinux_write_opts(m, &opts);
1005 1009
@@ -1734,24 +1738,34 @@ static inline u32 file_to_av(struct file *file)
1734 1738
1735/* Hook functions begin here. */ 1739/* Hook functions begin here. */
1736 1740
1737static int selinux_ptrace(struct task_struct *parent, 1741static int selinux_ptrace_may_access(struct task_struct *child,
1738 struct task_struct *child, 1742 unsigned int mode)
1739 unsigned int mode)
1740{ 1743{
1741 int rc; 1744 int rc;
1742 1745
1743 rc = secondary_ops->ptrace(parent, child, mode); 1746 rc = secondary_ops->ptrace_may_access(child, mode);
1744 if (rc) 1747 if (rc)
1745 return rc; 1748 return rc;
1746 1749
1747 if (mode == PTRACE_MODE_READ) { 1750 if (mode == PTRACE_MODE_READ) {
1748 struct task_security_struct *tsec = parent->security; 1751 struct task_security_struct *tsec = current->security;
1749 struct task_security_struct *csec = child->security; 1752 struct task_security_struct *csec = child->security;
1750 return avc_has_perm(tsec->sid, csec->sid, 1753 return avc_has_perm(tsec->sid, csec->sid,
1751 SECCLASS_FILE, FILE__READ, NULL); 1754 SECCLASS_FILE, FILE__READ, NULL);
1752 } 1755 }
1753 1756
1754 return task_has_perm(parent, child, PROCESS__PTRACE); 1757 return task_has_perm(current, child, PROCESS__PTRACE);
1758}
1759
1760static int selinux_ptrace_traceme(struct task_struct *parent)
1761{
1762 int rc;
1763
1764 rc = secondary_ops->ptrace_traceme(parent);
1765 if (rc)
1766 return rc;
1767
1768 return task_has_perm(parent, current, PROCESS__PTRACE);
1755} 1769}
1756 1770
1757static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, 1771static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
@@ -1971,22 +1985,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1971 return __vm_enough_memory(mm, pages, cap_sys_admin); 1985 return __vm_enough_memory(mm, pages, cap_sys_admin);
1972} 1986}
1973 1987
1974/**
1975 * task_tracer_task - return the task that is tracing the given task
1976 * @task: task to consider
1977 *
1978 * Returns NULL if noone is tracing @task, or the &struct task_struct
1979 * pointer to its tracer.
1980 *
1981 * Must be called under rcu_read_lock().
1982 */
1983static struct task_struct *task_tracer_task(struct task_struct *task)
1984{
1985 if (task->ptrace & PT_PTRACED)
1986 return rcu_dereference(task->parent);
1987 return NULL;
1988}
1989
1990/* binprm security operations */ 1988/* binprm security operations */
1991 1989
1992static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 1990static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2238,7 +2236,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2238 u32 ptsid = 0; 2236 u32 ptsid = 0;
2239 2237
2240 rcu_read_lock(); 2238 rcu_read_lock();
2241 tracer = task_tracer_task(current); 2239 tracer = tracehook_tracer_task(current);
2242 if (likely(tracer != NULL)) { 2240 if (likely(tracer != NULL)) {
2243 sec = tracer->security; 2241 sec = tracer->security;
2244 ptsid = sec->sid; 2242 ptsid = sec->sid;
@@ -2640,12 +2638,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
2640 return dentry_has_perm(current, NULL, dentry, FILE__READ); 2638 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2641} 2639}
2642 2640
2643static int selinux_inode_permission(struct inode *inode, int mask, 2641static int selinux_inode_permission(struct inode *inode, int mask)
2644 struct nameidata *nd)
2645{ 2642{
2646 int rc; 2643 int rc;
2647 2644
2648 rc = secondary_ops->inode_permission(inode, mask, nd); 2645 rc = secondary_ops->inode_permission(inode, mask);
2649 if (rc) 2646 if (rc)
2650 return rc; 2647 return rc;
2651 2648
@@ -5247,7 +5244,7 @@ static int selinux_setprocattr(struct task_struct *p,
5247 Otherwise, leave SID unchanged and fail. */ 5244 Otherwise, leave SID unchanged and fail. */
5248 task_lock(p); 5245 task_lock(p);
5249 rcu_read_lock(); 5246 rcu_read_lock();
5250 tracer = task_tracer_task(p); 5247 tracer = tracehook_tracer_task(p);
5251 if (tracer != NULL) { 5248 if (tracer != NULL) {
5252 struct task_security_struct *ptsec = tracer->security; 5249 struct task_security_struct *ptsec = tracer->security;
5253 u32 ptsid = ptsec->sid; 5250 u32 ptsid = ptsec->sid;
@@ -5359,7 +5356,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
5359static struct security_operations selinux_ops = { 5356static struct security_operations selinux_ops = {
5360 .name = "selinux", 5357 .name = "selinux",
5361 5358
5362 .ptrace = selinux_ptrace, 5359 .ptrace_may_access = selinux_ptrace_may_access,
5360 .ptrace_traceme = selinux_ptrace_traceme,
5363 .capget = selinux_capget, 5361 .capget = selinux_capget,
5364 .capset_check = selinux_capset_check, 5362 .capset_check = selinux_capset_check,
5365 .capset_set = selinux_capset_set, 5363 .capset_set = selinux_capset_set,
@@ -5670,27 +5668,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
5670static int __init selinux_nf_ip_init(void) 5668static int __init selinux_nf_ip_init(void)
5671{ 5669{
5672 int err = 0; 5670 int err = 0;
5673 u32 iter;
5674 5671
5675 if (!selinux_enabled) 5672 if (!selinux_enabled)
5676 goto out; 5673 goto out;
5677 5674
5678 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 5675 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5679 5676
5680 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { 5677 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5681 err = nf_register_hook(&selinux_ipv4_ops[iter]); 5678 if (err)
5682 if (err) 5679 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
5683 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5684 err);
5685 }
5686 5680
5687#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5681#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5688 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { 5682 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5689 err = nf_register_hook(&selinux_ipv6_ops[iter]); 5683 if (err)
5690 if (err) 5684 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
5691 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5692 err);
5693 }
5694#endif /* IPV6 */ 5685#endif /* IPV6 */
5695 5686
5696out: 5687out:
@@ -5702,15 +5693,11 @@ __initcall(selinux_nf_ip_init);
5702#ifdef CONFIG_SECURITY_SELINUX_DISABLE 5693#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5703static void selinux_nf_ip_exit(void) 5694static void selinux_nf_ip_exit(void)
5704{ 5695{
5705 u32 iter;
5706
5707 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 5696 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
5708 5697
5709 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) 5698 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5710 nf_unregister_hook(&selinux_ipv4_ops[iter]);
5711#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5699#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5712 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) 5700 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5713 nf_unregister_hook(&selinux_ipv6_ops[iter]);
5714#endif /* IPV6 */ 5701#endif /* IPV6 */
5715} 5702}
5716#endif 5703#endif
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b52f923ce680..d11a8154500f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -811,11 +811,12 @@ static int string_to_context_struct(struct policydb *pol,
811 /* Check the validity of the new context. */ 811 /* Check the validity of the new context. */
812 if (!policydb_context_isvalid(pol, ctx)) { 812 if (!policydb_context_isvalid(pol, ctx)) {
813 rc = -EINVAL; 813 rc = -EINVAL;
814 context_destroy(ctx);
815 goto out; 814 goto out;
816 } 815 }
817 rc = 0; 816 rc = 0;
818out: 817out:
818 if (rc)
819 context_destroy(ctx);
819 return rc; 820 return rc;
820} 821}
821 822
@@ -868,8 +869,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
868 } else if (rc) 869 } else if (rc)
869 goto out; 870 goto out;
870 rc = sidtab_context_to_sid(&sidtab, &context, sid); 871 rc = sidtab_context_to_sid(&sidtab, &context, sid);
871 if (rc) 872 context_destroy(&context);
872 context_destroy(&context);
873out: 873out:
874 read_unlock(&policy_rwlock); 874 read_unlock(&policy_rwlock);
875 kfree(scontext2); 875 kfree(scontext2);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index ee5a51cbc5eb..87d75417ea93 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -87,27 +87,46 @@ struct inode_smack *new_inode_smack(char *smack)
87 */ 87 */
88 88
89/** 89/**
90 * smack_ptrace - Smack approval on ptrace 90 * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH
91 * @ptp: parent task pointer
92 * @ctp: child task pointer 91 * @ctp: child task pointer
93 * 92 *
94 * Returns 0 if access is OK, an error code otherwise 93 * Returns 0 if access is OK, an error code otherwise
95 * 94 *
96 * Do the capability checks, and require read and write. 95 * Do the capability checks, and require read and write.
97 */ 96 */
98static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp, 97static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
99 unsigned int mode)
100{ 98{
101 int rc; 99 int rc;
102 100
103 rc = cap_ptrace(ptp, ctp, mode); 101 rc = cap_ptrace_may_access(ctp, mode);
104 if (rc != 0) 102 if (rc != 0)
105 return rc; 103 return rc;
106 104
107 rc = smk_access(ptp->security, ctp->security, MAY_READWRITE); 105 rc = smk_access(current->security, ctp->security, MAY_READWRITE);
108 if (rc != 0 && __capable(ptp, CAP_MAC_OVERRIDE)) 106 if (rc != 0 && capable(CAP_MAC_OVERRIDE))
109 return 0; 107 return 0;
108 return rc;
109}
110
111/**
112 * smack_ptrace_traceme - Smack approval on PTRACE_TRACEME
113 * @ptp: parent task pointer
114 *
115 * Returns 0 if access is OK, an error code otherwise
116 *
117 * Do the capability checks, and require read and write.
118 */
119static int smack_ptrace_traceme(struct task_struct *ptp)
120{
121 int rc;
122
123 rc = cap_ptrace_traceme(ptp);
124 if (rc != 0)
125 return rc;
110 126
127 rc = smk_access(ptp->security, current->security, MAY_READWRITE);
128 if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
129 return 0;
111 return rc; 130 return rc;
112} 131}
113 132
@@ -522,8 +541,7 @@ static int smack_inode_rename(struct inode *old_inode,
522 * 541 *
523 * Returns 0 if access is permitted, -EACCES otherwise 542 * Returns 0 if access is permitted, -EACCES otherwise
524 */ 543 */
525static int smack_inode_permission(struct inode *inode, int mask, 544static int smack_inode_permission(struct inode *inode, int mask)
526 struct nameidata *nd)
527{ 545{
528 /* 546 /*
529 * No permission to check. Existence test. Yup, it's there. 547 * No permission to check. Existence test. Yup, it's there.
@@ -924,7 +942,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
924 */ 942 */
925 file = container_of(fown, struct file, f_owner); 943 file = container_of(fown, struct file, f_owner);
926 rc = smk_access(file->f_security, tsk->security, MAY_WRITE); 944 rc = smk_access(file->f_security, tsk->security, MAY_WRITE);
927 if (rc != 0 && __capable(tsk, CAP_MAC_OVERRIDE)) 945 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
928 return 0; 946 return 0;
929 return rc; 947 return rc;
930} 948}
@@ -1165,12 +1183,12 @@ static int smack_task_wait(struct task_struct *p)
1165 * account for the smack labels having gotten to 1183 * account for the smack labels having gotten to
1166 * be different in the first place. 1184 * be different in the first place.
1167 * 1185 *
1168 * This breaks the strict subjet/object access 1186 * This breaks the strict subject/object access
1169 * control ideal, taking the object's privilege 1187 * control ideal, taking the object's privilege
1170 * state into account in the decision as well as 1188 * state into account in the decision as well as
1171 * the smack value. 1189 * the smack value.
1172 */ 1190 */
1173 if (capable(CAP_MAC_OVERRIDE) || __capable(p, CAP_MAC_OVERRIDE)) 1191 if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
1174 return 0; 1192 return 0;
1175 1193
1176 return rc; 1194 return rc;
@@ -2017,9 +2035,6 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2017{ 2035{
2018 char *newsmack; 2036 char *newsmack;
2019 2037
2020 if (!__capable(p, CAP_MAC_ADMIN))
2021 return -EPERM;
2022
2023 /* 2038 /*
2024 * Changing another process' Smack value is too dangerous 2039 * Changing another process' Smack value is too dangerous
2025 * and supports no sane use case. 2040 * and supports no sane use case.
@@ -2027,6 +2042,9 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2027 if (p != current) 2042 if (p != current)
2028 return -EPERM; 2043 return -EPERM;
2029 2044
2045 if (!capable(CAP_MAC_ADMIN))
2046 return -EPERM;
2047
2030 if (value == NULL || size == 0 || size >= SMK_LABELLEN) 2048 if (value == NULL || size == 0 || size >= SMK_LABELLEN)
2031 return -EINVAL; 2049 return -EINVAL;
2032 2050
@@ -2553,7 +2571,8 @@ static void smack_release_secctx(char *secdata, u32 seclen)
2553struct security_operations smack_ops = { 2571struct security_operations smack_ops = {
2554 .name = "smack", 2572 .name = "smack",
2555 2573
2556 .ptrace = smack_ptrace, 2574 .ptrace_may_access = smack_ptrace_may_access,
2575 .ptrace_traceme = smack_ptrace_traceme,
2557 .capget = cap_capget, 2576 .capget = cap_capget,
2558 .capset_check = cap_capset_check, 2577 .capset_check = cap_capset_check,
2559 .capset_set = cap_capset_set, 2578 .capset_set = cap_capset_set,
@@ -2730,4 +2749,3 @@ static __init int smack_init(void)
2730 * all processes and objects when they are created. 2749 * all processes and objects when they are created.
2731 */ 2750 */
2732security_initcall(smack_init); 2751security_initcall(smack_init);
2733