aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c193
1 files changed, 151 insertions, 42 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 28832e689800..2e8b4dfcbc74 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -18,7 +18,6 @@
18 * as published by the Free Software Foundation. 18 * as published by the Free Software Foundation.
19 */ 19 */
20 20
21#include <linux/config.h>
22#include <linux/module.h> 21#include <linux/module.h>
23#include <linux/init.h> 22#include <linux/init.h>
24#include <linux/kernel.h> 23#include <linux/kernel.h>
@@ -69,6 +68,7 @@
69#include <linux/sysctl.h> 68#include <linux/sysctl.h>
70#include <linux/audit.h> 69#include <linux/audit.h>
71#include <linux/string.h> 70#include <linux/string.h>
71#include <linux/selinux.h>
72 72
73#include "avc.h" 73#include "avc.h"
74#include "objsec.h" 74#include "objsec.h"
@@ -246,6 +246,7 @@ static int superblock_alloc_security(struct super_block *sb)
246 sbsec->sb = sb; 246 sbsec->sb = sb;
247 sbsec->sid = SECINITSID_UNLABELED; 247 sbsec->sid = SECINITSID_UNLABELED;
248 sbsec->def_sid = SECINITSID_FILE; 248 sbsec->def_sid = SECINITSID_FILE;
249 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
249 sb->s_security = sbsec; 250 sb->s_security = sbsec;
250 251
251 return 0; 252 return 0;
@@ -319,19 +320,53 @@ enum {
319 Opt_context = 1, 320 Opt_context = 1,
320 Opt_fscontext = 2, 321 Opt_fscontext = 2,
321 Opt_defcontext = 4, 322 Opt_defcontext = 4,
323 Opt_rootcontext = 8,
322}; 324};
323 325
324static match_table_t tokens = { 326static match_table_t tokens = {
325 {Opt_context, "context=%s"}, 327 {Opt_context, "context=%s"},
326 {Opt_fscontext, "fscontext=%s"}, 328 {Opt_fscontext, "fscontext=%s"},
327 {Opt_defcontext, "defcontext=%s"}, 329 {Opt_defcontext, "defcontext=%s"},
330 {Opt_rootcontext, "rootcontext=%s"},
328}; 331};
329 332
330#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" 333#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
331 334
335static int may_context_mount_sb_relabel(u32 sid,
336 struct superblock_security_struct *sbsec,
337 struct task_security_struct *tsec)
338{
339 int rc;
340
341 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
342 FILESYSTEM__RELABELFROM, NULL);
343 if (rc)
344 return rc;
345
346 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
347 FILESYSTEM__RELABELTO, NULL);
348 return rc;
349}
350
351static int may_context_mount_inode_relabel(u32 sid,
352 struct superblock_security_struct *sbsec,
353 struct task_security_struct *tsec)
354{
355 int rc;
356 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
357 FILESYSTEM__RELABELFROM, NULL);
358 if (rc)
359 return rc;
360
361 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
362 FILESYSTEM__ASSOCIATE, NULL);
363 return rc;
364}
365
332static int try_context_mount(struct super_block *sb, void *data) 366static int try_context_mount(struct super_block *sb, void *data)
333{ 367{
334 char *context = NULL, *defcontext = NULL; 368 char *context = NULL, *defcontext = NULL;
369 char *fscontext = NULL, *rootcontext = NULL;
335 const char *name; 370 const char *name;
336 u32 sid; 371 u32 sid;
337 int alloc = 0, rc = 0, seen = 0; 372 int alloc = 0, rc = 0, seen = 0;
@@ -374,7 +409,7 @@ static int try_context_mount(struct super_block *sb, void *data)
374 409
375 switch (token) { 410 switch (token) {
376 case Opt_context: 411 case Opt_context:
377 if (seen) { 412 if (seen & (Opt_context|Opt_defcontext)) {
378 rc = -EINVAL; 413 rc = -EINVAL;
379 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); 414 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
380 goto out_free; 415 goto out_free;
@@ -390,13 +425,13 @@ static int try_context_mount(struct super_block *sb, void *data)
390 break; 425 break;
391 426
392 case Opt_fscontext: 427 case Opt_fscontext:
393 if (seen & (Opt_context|Opt_fscontext)) { 428 if (seen & Opt_fscontext) {
394 rc = -EINVAL; 429 rc = -EINVAL;
395 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); 430 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
396 goto out_free; 431 goto out_free;
397 } 432 }
398 context = match_strdup(&args[0]); 433 fscontext = match_strdup(&args[0]);
399 if (!context) { 434 if (!fscontext) {
400 rc = -ENOMEM; 435 rc = -ENOMEM;
401 goto out_free; 436 goto out_free;
402 } 437 }
@@ -405,6 +440,22 @@ static int try_context_mount(struct super_block *sb, void *data)
405 seen |= Opt_fscontext; 440 seen |= Opt_fscontext;
406 break; 441 break;
407 442
443 case Opt_rootcontext:
444 if (seen & Opt_rootcontext) {
445 rc = -EINVAL;
446 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
447 goto out_free;
448 }
449 rootcontext = match_strdup(&args[0]);
450 if (!rootcontext) {
451 rc = -ENOMEM;
452 goto out_free;
453 }
454 if (!alloc)
455 alloc = 1;
456 seen |= Opt_rootcontext;
457 break;
458
408 case Opt_defcontext: 459 case Opt_defcontext:
409 if (sbsec->behavior != SECURITY_FS_USE_XATTR) { 460 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
410 rc = -EINVAL; 461 rc = -EINVAL;
@@ -441,6 +492,28 @@ static int try_context_mount(struct super_block *sb, void *data)
441 if (!seen) 492 if (!seen)
442 goto out; 493 goto out;
443 494
495 /* sets the context of the superblock for the fs being mounted. */
496 if (fscontext) {
497 rc = security_context_to_sid(fscontext, strlen(fscontext), &sid);
498 if (rc) {
499 printk(KERN_WARNING "SELinux: security_context_to_sid"
500 "(%s) failed for (dev %s, type %s) errno=%d\n",
501 fscontext, sb->s_id, name, rc);
502 goto out_free;
503 }
504
505 rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
506 if (rc)
507 goto out_free;
508
509 sbsec->sid = sid;
510 }
511
512 /*
513 * Switch to using mount point labeling behavior.
514 * sets the label used on all file below the mountpoint, and will set
515 * the superblock context if not already set.
516 */
444 if (context) { 517 if (context) {
445 rc = security_context_to_sid(context, strlen(context), &sid); 518 rc = security_context_to_sid(context, strlen(context), &sid);
446 if (rc) { 519 if (rc) {
@@ -450,20 +523,34 @@ static int try_context_mount(struct super_block *sb, void *data)
450 goto out_free; 523 goto out_free;
451 } 524 }
452 525
453 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, 526 rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
454 FILESYSTEM__RELABELFROM, NULL);
455 if (rc) 527 if (rc)
456 goto out_free; 528 goto out_free;
457 529
458 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, 530 if (!fscontext)
459 FILESYSTEM__RELABELTO, NULL); 531 sbsec->sid = sid;
460 if (rc) 532 sbsec->mntpoint_sid = sid;
533
534 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
535 }
536
537 if (rootcontext) {
538 struct inode *inode = sb->s_root->d_inode;
539 struct inode_security_struct *isec = inode->i_security;
540 rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);
541 if (rc) {
542 printk(KERN_WARNING "SELinux: security_context_to_sid"
543 "(%s) failed for (dev %s, type %s) errno=%d\n",
544 rootcontext, sb->s_id, name, rc);
461 goto out_free; 545 goto out_free;
546 }
462 547
463 sbsec->sid = sid; 548 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
549 if (rc)
550 goto out_free;
464 551
465 if (seen & Opt_context) 552 isec->sid = sid;
466 sbsec->behavior = SECURITY_FS_USE_MNTPOINT; 553 isec->initialized = 1;
467 } 554 }
468 555
469 if (defcontext) { 556 if (defcontext) {
@@ -478,13 +565,7 @@ static int try_context_mount(struct super_block *sb, void *data)
478 if (sid == sbsec->def_sid) 565 if (sid == sbsec->def_sid)
479 goto out_free; 566 goto out_free;
480 567
481 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, 568 rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
482 FILESYSTEM__RELABELFROM, NULL);
483 if (rc)
484 goto out_free;
485
486 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
487 FILESYSTEM__ASSOCIATE, NULL);
488 if (rc) 569 if (rc)
489 goto out_free; 570 goto out_free;
490 571
@@ -495,6 +576,8 @@ out_free:
495 if (alloc) { 576 if (alloc) {
496 kfree(context); 577 kfree(context);
497 kfree(defcontext); 578 kfree(defcontext);
579 kfree(fscontext);
580 kfree(rootcontext);
498 } 581 }
499out: 582out:
500 return rc; 583 return rc;
@@ -876,8 +959,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
876 goto out; 959 goto out;
877 isec->sid = sid; 960 isec->sid = sid;
878 break; 961 break;
962 case SECURITY_FS_USE_MNTPOINT:
963 isec->sid = sbsec->mntpoint_sid;
964 break;
879 default: 965 default:
880 /* Default to the fs SID. */ 966 /* Default to the fs superblock SID. */
881 isec->sid = sbsec->sid; 967 isec->sid = sbsec->sid;
882 968
883 if (sbsec->proc) { 969 if (sbsec->proc) {
@@ -1843,7 +1929,8 @@ static inline int selinux_option(char *option, int len)
1843{ 1929{
1844 return (match_prefix("context=", sizeof("context=")-1, option, len) || 1930 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
1845 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) || 1931 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
1846 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len)); 1932 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
1933 match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
1847} 1934}
1848 1935
1849static inline void take_option(char **to, char *from, int *first, int len) 1936static inline void take_option(char **to, char *from, int *first, int len)
@@ -2643,6 +2730,11 @@ static int selinux_task_getsid(struct task_struct *p)
2643 return task_has_perm(current, p, PROCESS__GETSESSION); 2730 return task_has_perm(current, p, PROCESS__GETSESSION);
2644} 2731}
2645 2732
2733static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
2734{
2735 selinux_get_task_sid(p, secid);
2736}
2737
2646static int selinux_task_setgroups(struct group_info *group_info) 2738static int selinux_task_setgroups(struct group_info *group_info)
2647{ 2739{
2648 /* See the comment for setuid above. */ 2740 /* See the comment for setuid above. */
@@ -2665,6 +2757,11 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
2665 return task_has_perm(current, p, PROCESS__SETSCHED); 2757 return task_has_perm(current, p, PROCESS__SETSCHED);
2666} 2758}
2667 2759
2760static int selinux_task_getioprio(struct task_struct *p)
2761{
2762 return task_has_perm(current, p, PROCESS__GETSCHED);
2763}
2764
2668static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) 2765static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
2669{ 2766{
2670 struct rlimit *old_rlim = current->signal->rlim + resource; 2767 struct rlimit *old_rlim = current->signal->rlim + resource;
@@ -2699,12 +2796,14 @@ static int selinux_task_movememory(struct task_struct *p)
2699 return task_has_perm(current, p, PROCESS__SETSCHED); 2796 return task_has_perm(current, p, PROCESS__SETSCHED);
2700} 2797}
2701 2798
2702static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig) 2799static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
2800 int sig, u32 secid)
2703{ 2801{
2704 u32 perm; 2802 u32 perm;
2705 int rc; 2803 int rc;
2804 struct task_security_struct *tsec;
2706 2805
2707 rc = secondary_ops->task_kill(p, info, sig); 2806 rc = secondary_ops->task_kill(p, info, sig, secid);
2708 if (rc) 2807 if (rc)
2709 return rc; 2808 return rc;
2710 2809
@@ -2715,8 +2814,12 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int si
2715 perm = PROCESS__SIGNULL; /* null signal; existence test */ 2814 perm = PROCESS__SIGNULL; /* null signal; existence test */
2716 else 2815 else
2717 perm = signal_to_av(sig); 2816 perm = signal_to_av(sig);
2718 2817 tsec = p->security;
2719 return task_has_perm(current, p, perm); 2818 if (secid)
2819 rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL);
2820 else
2821 rc = task_has_perm(current, p, perm);
2822 return rc;
2720} 2823}
2721 2824
2722static int selinux_task_prctl(int option, 2825static int selinux_task_prctl(int option,
@@ -3420,7 +3523,13 @@ out:
3420static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) 3523static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
3421{ 3524{
3422 int err = 0; 3525 int err = 0;
3423 u32 peer_sid = selinux_socket_getpeer_dgram(skb); 3526 u32 peer_sid;
3527
3528 if (skb->sk->sk_family == PF_UNIX)
3529 selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket),
3530 &peer_sid);
3531 else
3532 peer_sid = selinux_socket_getpeer_dgram(skb);
3424 3533
3425 if (peer_sid == SECSID_NULL) 3534 if (peer_sid == SECSID_NULL)
3426 return -EINVAL; 3535 return -EINVAL;
@@ -3432,8 +3541,6 @@ static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
3432 return 0; 3541 return 0;
3433} 3542}
3434 3543
3435
3436
3437static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 3544static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
3438{ 3545{
3439 return sk_alloc_security(sk, family, priority); 3546 return sk_alloc_security(sk, family, priority);
@@ -3641,32 +3748,32 @@ static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum,
3641 3748
3642static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) 3749static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
3643{ 3750{
3644 struct task_security_struct *tsec;
3645 struct av_decision avd;
3646 int err; 3751 int err;
3647 3752
3648 err = secondary_ops->netlink_send(sk, skb); 3753 err = secondary_ops->netlink_send(sk, skb);
3649 if (err) 3754 if (err)
3650 return err; 3755 return err;
3651 3756
3652 tsec = current->security;
3653
3654 avd.allowed = 0;
3655 avc_has_perm_noaudit(tsec->sid, tsec->sid,
3656 SECCLASS_CAPABILITY, ~0, &avd);
3657 cap_mask(NETLINK_CB(skb).eff_cap, avd.allowed);
3658
3659 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) 3757 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
3660 err = selinux_nlmsg_perm(sk, skb); 3758 err = selinux_nlmsg_perm(sk, skb);
3661 3759
3662 return err; 3760 return err;
3663} 3761}
3664 3762
3665static int selinux_netlink_recv(struct sk_buff *skb) 3763static int selinux_netlink_recv(struct sk_buff *skb, int capability)
3666{ 3764{
3667 if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) 3765 int err;
3668 return -EPERM; 3766 struct avc_audit_data ad;
3669 return 0; 3767
3768 err = secondary_ops->netlink_recv(skb, capability);
3769 if (err)
3770 return err;
3771
3772 AVC_AUDIT_DATA_INIT(&ad, CAP);
3773 ad.u.cap = capability;
3774
3775 return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
3776 SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
3670} 3777}
3671 3778
3672static int ipc_alloc_security(struct task_struct *task, 3779static int ipc_alloc_security(struct task_struct *task,
@@ -4429,9 +4536,11 @@ static struct security_operations selinux_ops = {
4429 .task_setpgid = selinux_task_setpgid, 4536 .task_setpgid = selinux_task_setpgid,
4430 .task_getpgid = selinux_task_getpgid, 4537 .task_getpgid = selinux_task_getpgid,
4431 .task_getsid = selinux_task_getsid, 4538 .task_getsid = selinux_task_getsid,
4539 .task_getsecid = selinux_task_getsecid,
4432 .task_setgroups = selinux_task_setgroups, 4540 .task_setgroups = selinux_task_setgroups,
4433 .task_setnice = selinux_task_setnice, 4541 .task_setnice = selinux_task_setnice,
4434 .task_setioprio = selinux_task_setioprio, 4542 .task_setioprio = selinux_task_setioprio,
4543 .task_getioprio = selinux_task_getioprio,
4435 .task_setrlimit = selinux_task_setrlimit, 4544 .task_setrlimit = selinux_task_setrlimit,
4436 .task_setscheduler = selinux_task_setscheduler, 4545 .task_setscheduler = selinux_task_setscheduler,
4437 .task_getscheduler = selinux_task_getscheduler, 4546 .task_getscheduler = selinux_task_getscheduler,