diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/avc.c | 205 | ||||
-rw-r--r-- | security/selinux/hooks.c | 174 | ||||
-rw-r--r-- | security/selinux/include/av_perm_to_string.h | 1 | ||||
-rw-r--r-- | security/selinux/include/av_permissions.h | 1 | ||||
-rw-r--r-- | security/selinux/include/avc.h | 55 | ||||
-rw-r--r-- | security/selinux/include/netlabel.h | 4 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 8 | ||||
-rw-r--r-- | security/selinux/netlabel.c | 2 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 142 | ||||
-rw-r--r-- | security/selinux/xfrm.c | 4 |
10 files changed, 281 insertions, 315 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b2ab60859832..e3d19014259b 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) | |||
137 | * @tclass: target security class | 137 | * @tclass: target security class |
138 | * @av: access vector | 138 | * @av: access vector |
139 | */ | 139 | */ |
140 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | 140 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) |
141 | { | 141 | { |
142 | const char **common_pts = NULL; | 142 | const char **common_pts = NULL; |
143 | u32 common_base = 0; | 143 | u32 common_base = 0; |
@@ -492,23 +492,35 @@ out: | |||
492 | return node; | 492 | return node; |
493 | } | 493 | } |
494 | 494 | ||
495 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 495 | /** |
496 | struct in6_addr *addr, __be16 port, | 496 | * avc_audit_pre_callback - SELinux specific information |
497 | char *name1, char *name2) | 497 | * will be called by generic audit code |
498 | * @ab: the audit buffer | ||
499 | * @a: audit_data | ||
500 | */ | ||
501 | static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | ||
498 | { | 502 | { |
499 | if (!ipv6_addr_any(addr)) | 503 | struct common_audit_data *ad = a; |
500 | audit_log_format(ab, " %s=%pI6", name1, addr); | 504 | audit_log_format(ab, "avc: %s ", |
501 | if (port) | 505 | ad->selinux_audit_data.denied ? "denied" : "granted"); |
502 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 506 | avc_dump_av(ab, ad->selinux_audit_data.tclass, |
507 | ad->selinux_audit_data.audited); | ||
508 | audit_log_format(ab, " for "); | ||
503 | } | 509 | } |
504 | 510 | ||
505 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | 511 | /** |
506 | __be16 port, char *name1, char *name2) | 512 | * avc_audit_post_callback - SELinux specific information |
513 | * will be called by generic audit code | ||
514 | * @ab: the audit buffer | ||
515 | * @a: audit_data | ||
516 | */ | ||
517 | static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||
507 | { | 518 | { |
508 | if (addr) | 519 | struct common_audit_data *ad = a; |
509 | audit_log_format(ab, " %s=%pI4", name1, &addr); | 520 | audit_log_format(ab, " "); |
510 | if (port) | 521 | avc_dump_query(ab, ad->selinux_audit_data.ssid, |
511 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 522 | ad->selinux_audit_data.tsid, |
523 | ad->selinux_audit_data.tclass); | ||
512 | } | 524 | } |
513 | 525 | ||
514 | /** | 526 | /** |
@@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | |||
532 | */ | 544 | */ |
533 | void avc_audit(u32 ssid, u32 tsid, | 545 | void avc_audit(u32 ssid, u32 tsid, |
534 | u16 tclass, u32 requested, | 546 | u16 tclass, u32 requested, |
535 | struct av_decision *avd, int result, struct avc_audit_data *a) | 547 | struct av_decision *avd, int result, struct common_audit_data *a) |
536 | { | 548 | { |
537 | struct task_struct *tsk = current; | 549 | struct common_audit_data stack_data; |
538 | struct inode *inode = NULL; | ||
539 | u32 denied, audited; | 550 | u32 denied, audited; |
540 | struct audit_buffer *ab; | ||
541 | |||
542 | denied = requested & ~avd->allowed; | 551 | denied = requested & ~avd->allowed; |
543 | if (denied) { | 552 | if (denied) { |
544 | audited = denied; | 553 | audited = denied; |
@@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid, | |||
551 | if (!(audited & avd->auditallow)) | 560 | if (!(audited & avd->auditallow)) |
552 | return; | 561 | return; |
553 | } | 562 | } |
554 | 563 | if (!a) { | |
555 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 564 | a = &stack_data; |
556 | if (!ab) | 565 | memset(a, 0, sizeof(*a)); |
557 | return; /* audit_panic has been called */ | 566 | a->type = LSM_AUDIT_NO_AUDIT; |
558 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | ||
559 | avc_dump_av(ab, tclass, audited); | ||
560 | audit_log_format(ab, " for "); | ||
561 | if (a && a->tsk) | ||
562 | tsk = a->tsk; | ||
563 | if (tsk && tsk->pid) { | ||
564 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
565 | audit_log_untrustedstring(ab, tsk->comm); | ||
566 | } | 567 | } |
567 | if (a) { | 568 | a->selinux_audit_data.tclass = tclass; |
568 | switch (a->type) { | 569 | a->selinux_audit_data.requested = requested; |
569 | case AVC_AUDIT_DATA_IPC: | 570 | a->selinux_audit_data.ssid = ssid; |
570 | audit_log_format(ab, " key=%d", a->u.ipc_id); | 571 | a->selinux_audit_data.tsid = tsid; |
571 | break; | 572 | a->selinux_audit_data.audited = audited; |
572 | case AVC_AUDIT_DATA_CAP: | 573 | a->selinux_audit_data.denied = denied; |
573 | audit_log_format(ab, " capability=%d", a->u.cap); | 574 | a->lsm_pre_audit = avc_audit_pre_callback; |
574 | break; | 575 | a->lsm_post_audit = avc_audit_post_callback; |
575 | case AVC_AUDIT_DATA_FS: | 576 | common_lsm_audit(a); |
576 | if (a->u.fs.path.dentry) { | ||
577 | struct dentry *dentry = a->u.fs.path.dentry; | ||
578 | if (a->u.fs.path.mnt) { | ||
579 | audit_log_d_path(ab, "path=", | ||
580 | &a->u.fs.path); | ||
581 | } else { | ||
582 | audit_log_format(ab, " name="); | ||
583 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
584 | } | ||
585 | inode = dentry->d_inode; | ||
586 | } else if (a->u.fs.inode) { | ||
587 | struct dentry *dentry; | ||
588 | inode = a->u.fs.inode; | ||
589 | dentry = d_find_alias(inode); | ||
590 | if (dentry) { | ||
591 | audit_log_format(ab, " name="); | ||
592 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
593 | dput(dentry); | ||
594 | } | ||
595 | } | ||
596 | if (inode) | ||
597 | audit_log_format(ab, " dev=%s ino=%lu", | ||
598 | inode->i_sb->s_id, | ||
599 | inode->i_ino); | ||
600 | break; | ||
601 | case AVC_AUDIT_DATA_NET: | ||
602 | if (a->u.net.sk) { | ||
603 | struct sock *sk = a->u.net.sk; | ||
604 | struct unix_sock *u; | ||
605 | int len = 0; | ||
606 | char *p = NULL; | ||
607 | |||
608 | switch (sk->sk_family) { | ||
609 | case AF_INET: { | ||
610 | struct inet_sock *inet = inet_sk(sk); | ||
611 | |||
612 | avc_print_ipv4_addr(ab, inet->rcv_saddr, | ||
613 | inet->sport, | ||
614 | "laddr", "lport"); | ||
615 | avc_print_ipv4_addr(ab, inet->daddr, | ||
616 | inet->dport, | ||
617 | "faddr", "fport"); | ||
618 | break; | ||
619 | } | ||
620 | case AF_INET6: { | ||
621 | struct inet_sock *inet = inet_sk(sk); | ||
622 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
623 | |||
624 | avc_print_ipv6_addr(ab, &inet6->rcv_saddr, | ||
625 | inet->sport, | ||
626 | "laddr", "lport"); | ||
627 | avc_print_ipv6_addr(ab, &inet6->daddr, | ||
628 | inet->dport, | ||
629 | "faddr", "fport"); | ||
630 | break; | ||
631 | } | ||
632 | case AF_UNIX: | ||
633 | u = unix_sk(sk); | ||
634 | if (u->dentry) { | ||
635 | struct path path = { | ||
636 | .dentry = u->dentry, | ||
637 | .mnt = u->mnt | ||
638 | }; | ||
639 | audit_log_d_path(ab, "path=", | ||
640 | &path); | ||
641 | break; | ||
642 | } | ||
643 | if (!u->addr) | ||
644 | break; | ||
645 | len = u->addr->len-sizeof(short); | ||
646 | p = &u->addr->name->sun_path[0]; | ||
647 | audit_log_format(ab, " path="); | ||
648 | if (*p) | ||
649 | audit_log_untrustedstring(ab, p); | ||
650 | else | ||
651 | audit_log_n_hex(ab, p, len); | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | switch (a->u.net.family) { | ||
657 | case AF_INET: | ||
658 | avc_print_ipv4_addr(ab, a->u.net.v4info.saddr, | ||
659 | a->u.net.sport, | ||
660 | "saddr", "src"); | ||
661 | avc_print_ipv4_addr(ab, a->u.net.v4info.daddr, | ||
662 | a->u.net.dport, | ||
663 | "daddr", "dest"); | ||
664 | break; | ||
665 | case AF_INET6: | ||
666 | avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr, | ||
667 | a->u.net.sport, | ||
668 | "saddr", "src"); | ||
669 | avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr, | ||
670 | a->u.net.dport, | ||
671 | "daddr", "dest"); | ||
672 | break; | ||
673 | } | ||
674 | if (a->u.net.netif > 0) { | ||
675 | struct net_device *dev; | ||
676 | |||
677 | /* NOTE: we always use init's namespace */ | ||
678 | dev = dev_get_by_index(&init_net, | ||
679 | a->u.net.netif); | ||
680 | if (dev) { | ||
681 | audit_log_format(ab, " netif=%s", | ||
682 | dev->name); | ||
683 | dev_put(dev); | ||
684 | } | ||
685 | } | ||
686 | break; | ||
687 | } | ||
688 | } | ||
689 | audit_log_format(ab, " "); | ||
690 | avc_dump_query(ab, ssid, tsid, tclass); | ||
691 | audit_log_end(ab); | ||
692 | } | 577 | } |
693 | 578 | ||
694 | /** | 579 | /** |
@@ -956,7 +841,7 @@ out: | |||
956 | * another -errno upon other errors. | 841 | * another -errno upon other errors. |
957 | */ | 842 | */ |
958 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | 843 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, |
959 | u32 requested, struct avc_audit_data *auditdata) | 844 | u32 requested, struct common_audit_data *auditdata) |
960 | { | 845 | { |
961 | struct av_decision avd; | 846 | struct av_decision avd; |
962 | int rc; | 847 | int rc; |
@@ -970,3 +855,9 @@ u32 avc_policy_seqno(void) | |||
970 | { | 855 | { |
971 | return avc_cache.latest_notif; | 856 | return avc_cache.latest_notif; |
972 | } | 857 | } |
858 | |||
859 | void avc_disable(void) | ||
860 | { | ||
861 | if (avc_node_cachep) | ||
862 | kmem_cache_destroy(avc_node_cachep); | ||
863 | } | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8d8b69c5664e..6d0b1ccb5b99 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1479,14 +1479,14 @@ static int task_has_capability(struct task_struct *tsk, | |||
1479 | const struct cred *cred, | 1479 | const struct cred *cred, |
1480 | int cap, int audit) | 1480 | int cap, int audit) |
1481 | { | 1481 | { |
1482 | struct avc_audit_data ad; | 1482 | struct common_audit_data ad; |
1483 | struct av_decision avd; | 1483 | struct av_decision avd; |
1484 | u16 sclass; | 1484 | u16 sclass; |
1485 | u32 sid = cred_sid(cred); | 1485 | u32 sid = cred_sid(cred); |
1486 | u32 av = CAP_TO_MASK(cap); | 1486 | u32 av = CAP_TO_MASK(cap); |
1487 | int rc; | 1487 | int rc; |
1488 | 1488 | ||
1489 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 1489 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
1490 | ad.tsk = tsk; | 1490 | ad.tsk = tsk; |
1491 | ad.u.cap = cap; | 1491 | ad.u.cap = cap; |
1492 | 1492 | ||
@@ -1525,10 +1525,10 @@ static int task_has_system(struct task_struct *tsk, | |||
1525 | static int inode_has_perm(const struct cred *cred, | 1525 | static int inode_has_perm(const struct cred *cred, |
1526 | struct inode *inode, | 1526 | struct inode *inode, |
1527 | u32 perms, | 1527 | u32 perms, |
1528 | struct avc_audit_data *adp) | 1528 | struct common_audit_data *adp) |
1529 | { | 1529 | { |
1530 | struct inode_security_struct *isec; | 1530 | struct inode_security_struct *isec; |
1531 | struct avc_audit_data ad; | 1531 | struct common_audit_data ad; |
1532 | u32 sid; | 1532 | u32 sid; |
1533 | 1533 | ||
1534 | if (unlikely(IS_PRIVATE(inode))) | 1534 | if (unlikely(IS_PRIVATE(inode))) |
@@ -1539,7 +1539,7 @@ static int inode_has_perm(const struct cred *cred, | |||
1539 | 1539 | ||
1540 | if (!adp) { | 1540 | if (!adp) { |
1541 | adp = &ad; | 1541 | adp = &ad; |
1542 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1542 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1543 | ad.u.fs.inode = inode; | 1543 | ad.u.fs.inode = inode; |
1544 | } | 1544 | } |
1545 | 1545 | ||
@@ -1555,9 +1555,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1555 | u32 av) | 1555 | u32 av) |
1556 | { | 1556 | { |
1557 | struct inode *inode = dentry->d_inode; | 1557 | struct inode *inode = dentry->d_inode; |
1558 | struct avc_audit_data ad; | 1558 | struct common_audit_data ad; |
1559 | 1559 | ||
1560 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1560 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1561 | ad.u.fs.path.mnt = mnt; | 1561 | ad.u.fs.path.mnt = mnt; |
1562 | ad.u.fs.path.dentry = dentry; | 1562 | ad.u.fs.path.dentry = dentry; |
1563 | return inode_has_perm(cred, inode, av, &ad); | 1563 | return inode_has_perm(cred, inode, av, &ad); |
@@ -1577,11 +1577,11 @@ static int file_has_perm(const struct cred *cred, | |||
1577 | { | 1577 | { |
1578 | struct file_security_struct *fsec = file->f_security; | 1578 | struct file_security_struct *fsec = file->f_security; |
1579 | struct inode *inode = file->f_path.dentry->d_inode; | 1579 | struct inode *inode = file->f_path.dentry->d_inode; |
1580 | struct avc_audit_data ad; | 1580 | struct common_audit_data ad; |
1581 | u32 sid = cred_sid(cred); | 1581 | u32 sid = cred_sid(cred); |
1582 | int rc; | 1582 | int rc; |
1583 | 1583 | ||
1584 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1584 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1585 | ad.u.fs.path = file->f_path; | 1585 | ad.u.fs.path = file->f_path; |
1586 | 1586 | ||
1587 | if (sid != fsec->sid) { | 1587 | if (sid != fsec->sid) { |
@@ -1612,7 +1612,7 @@ static int may_create(struct inode *dir, | |||
1612 | struct inode_security_struct *dsec; | 1612 | struct inode_security_struct *dsec; |
1613 | struct superblock_security_struct *sbsec; | 1613 | struct superblock_security_struct *sbsec; |
1614 | u32 sid, newsid; | 1614 | u32 sid, newsid; |
1615 | struct avc_audit_data ad; | 1615 | struct common_audit_data ad; |
1616 | int rc; | 1616 | int rc; |
1617 | 1617 | ||
1618 | dsec = dir->i_security; | 1618 | dsec = dir->i_security; |
@@ -1621,7 +1621,7 @@ static int may_create(struct inode *dir, | |||
1621 | sid = tsec->sid; | 1621 | sid = tsec->sid; |
1622 | newsid = tsec->create_sid; | 1622 | newsid = tsec->create_sid; |
1623 | 1623 | ||
1624 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1624 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1625 | ad.u.fs.path.dentry = dentry; | 1625 | ad.u.fs.path.dentry = dentry; |
1626 | 1626 | ||
1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
@@ -1665,7 +1665,7 @@ static int may_link(struct inode *dir, | |||
1665 | 1665 | ||
1666 | { | 1666 | { |
1667 | struct inode_security_struct *dsec, *isec; | 1667 | struct inode_security_struct *dsec, *isec; |
1668 | struct avc_audit_data ad; | 1668 | struct common_audit_data ad; |
1669 | u32 sid = current_sid(); | 1669 | u32 sid = current_sid(); |
1670 | u32 av; | 1670 | u32 av; |
1671 | int rc; | 1671 | int rc; |
@@ -1673,7 +1673,7 @@ static int may_link(struct inode *dir, | |||
1673 | dsec = dir->i_security; | 1673 | dsec = dir->i_security; |
1674 | isec = dentry->d_inode->i_security; | 1674 | isec = dentry->d_inode->i_security; |
1675 | 1675 | ||
1676 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1676 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1677 | ad.u.fs.path.dentry = dentry; | 1677 | ad.u.fs.path.dentry = dentry; |
1678 | 1678 | ||
1679 | av = DIR__SEARCH; | 1679 | av = DIR__SEARCH; |
@@ -1708,7 +1708,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1708 | struct dentry *new_dentry) | 1708 | struct dentry *new_dentry) |
1709 | { | 1709 | { |
1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1711 | struct avc_audit_data ad; | 1711 | struct common_audit_data ad; |
1712 | u32 sid = current_sid(); | 1712 | u32 sid = current_sid(); |
1713 | u32 av; | 1713 | u32 av; |
1714 | int old_is_dir, new_is_dir; | 1714 | int old_is_dir, new_is_dir; |
@@ -1719,7 +1719,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1720 | new_dsec = new_dir->i_security; | 1720 | new_dsec = new_dir->i_security; |
1721 | 1721 | ||
1722 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1722 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1723 | 1723 | ||
1724 | ad.u.fs.path.dentry = old_dentry; | 1724 | ad.u.fs.path.dentry = old_dentry; |
1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1761,7 +1761,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1761 | static int superblock_has_perm(const struct cred *cred, | 1761 | static int superblock_has_perm(const struct cred *cred, |
1762 | struct super_block *sb, | 1762 | struct super_block *sb, |
1763 | u32 perms, | 1763 | u32 perms, |
1764 | struct avc_audit_data *ad) | 1764 | struct common_audit_data *ad) |
1765 | { | 1765 | { |
1766 | struct superblock_security_struct *sbsec; | 1766 | struct superblock_security_struct *sbsec; |
1767 | u32 sid = cred_sid(cred); | 1767 | u32 sid = cred_sid(cred); |
@@ -1855,12 +1855,12 @@ static inline u32 open_file_to_av(struct file *file) | |||
1855 | 1855 | ||
1856 | /* Hook functions begin here. */ | 1856 | /* Hook functions begin here. */ |
1857 | 1857 | ||
1858 | static int selinux_ptrace_may_access(struct task_struct *child, | 1858 | static int selinux_ptrace_access_check(struct task_struct *child, |
1859 | unsigned int mode) | 1859 | unsigned int mode) |
1860 | { | 1860 | { |
1861 | int rc; | 1861 | int rc; |
1862 | 1862 | ||
1863 | rc = cap_ptrace_may_access(child, mode); | 1863 | rc = cap_ptrace_access_check(child, mode); |
1864 | if (rc) | 1864 | if (rc) |
1865 | return rc; | 1865 | return rc; |
1866 | 1866 | ||
@@ -2101,7 +2101,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2101 | const struct task_security_struct *old_tsec; | 2101 | const struct task_security_struct *old_tsec; |
2102 | struct task_security_struct *new_tsec; | 2102 | struct task_security_struct *new_tsec; |
2103 | struct inode_security_struct *isec; | 2103 | struct inode_security_struct *isec; |
2104 | struct avc_audit_data ad; | 2104 | struct common_audit_data ad; |
2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
2106 | int rc; | 2106 | int rc; |
2107 | 2107 | ||
@@ -2139,7 +2139,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2139 | return rc; | 2139 | return rc; |
2140 | } | 2140 | } |
2141 | 2141 | ||
2142 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2142 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2143 | ad.u.fs.path = bprm->file->f_path; | 2143 | ad.u.fs.path = bprm->file->f_path; |
2144 | 2144 | ||
2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
@@ -2232,7 +2232,7 @@ extern struct dentry *selinux_null; | |||
2232 | static inline void flush_unauthorized_files(const struct cred *cred, | 2232 | static inline void flush_unauthorized_files(const struct cred *cred, |
2233 | struct files_struct *files) | 2233 | struct files_struct *files) |
2234 | { | 2234 | { |
2235 | struct avc_audit_data ad; | 2235 | struct common_audit_data ad; |
2236 | struct file *file, *devnull = NULL; | 2236 | struct file *file, *devnull = NULL; |
2237 | struct tty_struct *tty; | 2237 | struct tty_struct *tty; |
2238 | struct fdtable *fdt; | 2238 | struct fdtable *fdt; |
@@ -2266,7 +2266,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2266 | 2266 | ||
2267 | /* Revalidate access to inherited open files. */ | 2267 | /* Revalidate access to inherited open files. */ |
2268 | 2268 | ||
2269 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2269 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2270 | 2270 | ||
2271 | spin_lock(&files->file_lock); | 2271 | spin_lock(&files->file_lock); |
2272 | for (;;) { | 2272 | for (;;) { |
@@ -2515,7 +2515,7 @@ out: | |||
2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2516 | { | 2516 | { |
2517 | const struct cred *cred = current_cred(); | 2517 | const struct cred *cred = current_cred(); |
2518 | struct avc_audit_data ad; | 2518 | struct common_audit_data ad; |
2519 | int rc; | 2519 | int rc; |
2520 | 2520 | ||
2521 | rc = superblock_doinit(sb, data); | 2521 | rc = superblock_doinit(sb, data); |
@@ -2526,7 +2526,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2526 | if (flags & MS_KERNMOUNT) | 2526 | if (flags & MS_KERNMOUNT) |
2527 | return 0; | 2527 | return 0; |
2528 | 2528 | ||
2529 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2529 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2530 | ad.u.fs.path.dentry = sb->s_root; | 2530 | ad.u.fs.path.dentry = sb->s_root; |
2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2532 | } | 2532 | } |
@@ -2534,9 +2534,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2534 | static int selinux_sb_statfs(struct dentry *dentry) | 2534 | static int selinux_sb_statfs(struct dentry *dentry) |
2535 | { | 2535 | { |
2536 | const struct cred *cred = current_cred(); | 2536 | const struct cred *cred = current_cred(); |
2537 | struct avc_audit_data ad; | 2537 | struct common_audit_data ad; |
2538 | 2538 | ||
2539 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2539 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; |
2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2542 | } | 2542 | } |
@@ -2756,7 +2756,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2756 | struct inode *inode = dentry->d_inode; | 2756 | struct inode *inode = dentry->d_inode; |
2757 | struct inode_security_struct *isec = inode->i_security; | 2757 | struct inode_security_struct *isec = inode->i_security; |
2758 | struct superblock_security_struct *sbsec; | 2758 | struct superblock_security_struct *sbsec; |
2759 | struct avc_audit_data ad; | 2759 | struct common_audit_data ad; |
2760 | u32 newsid, sid = current_sid(); | 2760 | u32 newsid, sid = current_sid(); |
2761 | int rc = 0; | 2761 | int rc = 0; |
2762 | 2762 | ||
@@ -2770,7 +2770,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2770 | if (!is_owner_or_cap(inode)) | 2770 | if (!is_owner_or_cap(inode)) |
2771 | return -EPERM; | 2771 | return -EPERM; |
2772 | 2772 | ||
2773 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2773 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2774 | ad.u.fs.path.dentry = dentry; | 2774 | ad.u.fs.path.dentry = dentry; |
2775 | 2775 | ||
2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2939,11 +2939,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2939 | const struct cred *cred = current_cred(); | 2939 | const struct cred *cred = current_cred(); |
2940 | struct inode *inode = file->f_path.dentry->d_inode; | 2940 | struct inode *inode = file->f_path.dentry->d_inode; |
2941 | 2941 | ||
2942 | if (!mask) { | ||
2943 | /* No permission to check. Existence test. */ | ||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2942 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2948 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2943 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2949 | mask |= MAY_APPEND; | 2944 | mask |= MAY_APPEND; |
@@ -2954,10 +2949,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2954 | 2949 | ||
2955 | static int selinux_file_permission(struct file *file, int mask) | 2950 | static int selinux_file_permission(struct file *file, int mask) |
2956 | { | 2951 | { |
2952 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2953 | struct file_security_struct *fsec = file->f_security; | ||
2954 | struct inode_security_struct *isec = inode->i_security; | ||
2955 | u32 sid = current_sid(); | ||
2956 | |||
2957 | if (!mask) | 2957 | if (!mask) |
2958 | /* No permission to check. Existence test. */ | 2958 | /* No permission to check. Existence test. */ |
2959 | return 0; | 2959 | return 0; |
2960 | 2960 | ||
2961 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
2962 | fsec->pseqno == avc_policy_seqno()) | ||
2963 | /* No change since dentry_open check. */ | ||
2964 | return 0; | ||
2965 | |||
2961 | return selinux_revalidate_file_permission(file, mask); | 2966 | return selinux_revalidate_file_permission(file, mask); |
2962 | } | 2967 | } |
2963 | 2968 | ||
@@ -3292,6 +3297,11 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3292 | return 0; | 3297 | return 0; |
3293 | } | 3298 | } |
3294 | 3299 | ||
3300 | static int selinux_kernel_module_request(void) | ||
3301 | { | ||
3302 | return task_has_system(current, SYSTEM__MODULE_REQUEST); | ||
3303 | } | ||
3304 | |||
3295 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3305 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3296 | { | 3306 | { |
3297 | return current_has_perm(p, PROCESS__SETPGID); | 3307 | return current_has_perm(p, PROCESS__SETPGID); |
@@ -3409,7 +3419,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3409 | 3419 | ||
3410 | /* Returns error only if unable to parse addresses */ | 3420 | /* Returns error only if unable to parse addresses */ |
3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3421 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3412 | struct avc_audit_data *ad, u8 *proto) | 3422 | struct common_audit_data *ad, u8 *proto) |
3413 | { | 3423 | { |
3414 | int offset, ihlen, ret = -EINVAL; | 3424 | int offset, ihlen, ret = -EINVAL; |
3415 | struct iphdr _iph, *ih; | 3425 | struct iphdr _iph, *ih; |
@@ -3490,7 +3500,7 @@ out: | |||
3490 | 3500 | ||
3491 | /* Returns error only if unable to parse addresses */ | 3501 | /* Returns error only if unable to parse addresses */ |
3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3502 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3493 | struct avc_audit_data *ad, u8 *proto) | 3503 | struct common_audit_data *ad, u8 *proto) |
3494 | { | 3504 | { |
3495 | u8 nexthdr; | 3505 | u8 nexthdr; |
3496 | int ret = -EINVAL, offset; | 3506 | int ret = -EINVAL, offset; |
@@ -3561,7 +3571,7 @@ out: | |||
3561 | 3571 | ||
3562 | #endif /* IPV6 */ | 3572 | #endif /* IPV6 */ |
3563 | 3573 | ||
3564 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3574 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
3565 | char **_addrp, int src, u8 *proto) | 3575 | char **_addrp, int src, u8 *proto) |
3566 | { | 3576 | { |
3567 | char *addrp; | 3577 | char *addrp; |
@@ -3643,7 +3653,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3643 | u32 perms) | 3653 | u32 perms) |
3644 | { | 3654 | { |
3645 | struct inode_security_struct *isec; | 3655 | struct inode_security_struct *isec; |
3646 | struct avc_audit_data ad; | 3656 | struct common_audit_data ad; |
3647 | u32 sid; | 3657 | u32 sid; |
3648 | int err = 0; | 3658 | int err = 0; |
3649 | 3659 | ||
@@ -3653,7 +3663,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3653 | goto out; | 3663 | goto out; |
3654 | sid = task_sid(task); | 3664 | sid = task_sid(task); |
3655 | 3665 | ||
3656 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3666 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3657 | ad.u.net.sk = sock->sk; | 3667 | ad.u.net.sk = sock->sk; |
3658 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 3668 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
3659 | 3669 | ||
@@ -3740,7 +3750,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3740 | if (family == PF_INET || family == PF_INET6) { | 3750 | if (family == PF_INET || family == PF_INET6) { |
3741 | char *addrp; | 3751 | char *addrp; |
3742 | struct inode_security_struct *isec; | 3752 | struct inode_security_struct *isec; |
3743 | struct avc_audit_data ad; | 3753 | struct common_audit_data ad; |
3744 | struct sockaddr_in *addr4 = NULL; | 3754 | struct sockaddr_in *addr4 = NULL; |
3745 | struct sockaddr_in6 *addr6 = NULL; | 3755 | struct sockaddr_in6 *addr6 = NULL; |
3746 | unsigned short snum; | 3756 | unsigned short snum; |
@@ -3769,7 +3779,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3769 | snum, &sid); | 3779 | snum, &sid); |
3770 | if (err) | 3780 | if (err) |
3771 | goto out; | 3781 | goto out; |
3772 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3782 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3773 | ad.u.net.sport = htons(snum); | 3783 | ad.u.net.sport = htons(snum); |
3774 | ad.u.net.family = family; | 3784 | ad.u.net.family = family; |
3775 | err = avc_has_perm(isec->sid, sid, | 3785 | err = avc_has_perm(isec->sid, sid, |
@@ -3802,7 +3812,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3802 | if (err) | 3812 | if (err) |
3803 | goto out; | 3813 | goto out; |
3804 | 3814 | ||
3805 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3815 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3806 | ad.u.net.sport = htons(snum); | 3816 | ad.u.net.sport = htons(snum); |
3807 | ad.u.net.family = family; | 3817 | ad.u.net.family = family; |
3808 | 3818 | ||
@@ -3836,7 +3846,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3836 | isec = SOCK_INODE(sock)->i_security; | 3846 | isec = SOCK_INODE(sock)->i_security; |
3837 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3847 | if (isec->sclass == SECCLASS_TCP_SOCKET || |
3838 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3848 | isec->sclass == SECCLASS_DCCP_SOCKET) { |
3839 | struct avc_audit_data ad; | 3849 | struct common_audit_data ad; |
3840 | struct sockaddr_in *addr4 = NULL; | 3850 | struct sockaddr_in *addr4 = NULL; |
3841 | struct sockaddr_in6 *addr6 = NULL; | 3851 | struct sockaddr_in6 *addr6 = NULL; |
3842 | unsigned short snum; | 3852 | unsigned short snum; |
@@ -3861,7 +3871,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3861 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3871 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? |
3862 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3872 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3863 | 3873 | ||
3864 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3874 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3865 | ad.u.net.dport = htons(snum); | 3875 | ad.u.net.dport = htons(snum); |
3866 | ad.u.net.family = sk->sk_family; | 3876 | ad.u.net.family = sk->sk_family; |
3867 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3877 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); |
@@ -3951,13 +3961,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
3951 | struct sk_security_struct *ssec; | 3961 | struct sk_security_struct *ssec; |
3952 | struct inode_security_struct *isec; | 3962 | struct inode_security_struct *isec; |
3953 | struct inode_security_struct *other_isec; | 3963 | struct inode_security_struct *other_isec; |
3954 | struct avc_audit_data ad; | 3964 | struct common_audit_data ad; |
3955 | int err; | 3965 | int err; |
3956 | 3966 | ||
3957 | isec = SOCK_INODE(sock)->i_security; | 3967 | isec = SOCK_INODE(sock)->i_security; |
3958 | other_isec = SOCK_INODE(other)->i_security; | 3968 | other_isec = SOCK_INODE(other)->i_security; |
3959 | 3969 | ||
3960 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3970 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3961 | ad.u.net.sk = other->sk; | 3971 | ad.u.net.sk = other->sk; |
3962 | 3972 | ||
3963 | err = avc_has_perm(isec->sid, other_isec->sid, | 3973 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -3983,13 +3993,13 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
3983 | { | 3993 | { |
3984 | struct inode_security_struct *isec; | 3994 | struct inode_security_struct *isec; |
3985 | struct inode_security_struct *other_isec; | 3995 | struct inode_security_struct *other_isec; |
3986 | struct avc_audit_data ad; | 3996 | struct common_audit_data ad; |
3987 | int err; | 3997 | int err; |
3988 | 3998 | ||
3989 | isec = SOCK_INODE(sock)->i_security; | 3999 | isec = SOCK_INODE(sock)->i_security; |
3990 | other_isec = SOCK_INODE(other)->i_security; | 4000 | other_isec = SOCK_INODE(other)->i_security; |
3991 | 4001 | ||
3992 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4002 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3993 | ad.u.net.sk = other->sk; | 4003 | ad.u.net.sk = other->sk; |
3994 | 4004 | ||
3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 4005 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -4002,7 +4012,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
4002 | 4012 | ||
4003 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 4013 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
4004 | u32 peer_sid, | 4014 | u32 peer_sid, |
4005 | struct avc_audit_data *ad) | 4015 | struct common_audit_data *ad) |
4006 | { | 4016 | { |
4007 | int err; | 4017 | int err; |
4008 | u32 if_sid; | 4018 | u32 if_sid; |
@@ -4030,10 +4040,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4030 | struct sk_security_struct *sksec = sk->sk_security; | 4040 | struct sk_security_struct *sksec = sk->sk_security; |
4031 | u32 peer_sid; | 4041 | u32 peer_sid; |
4032 | u32 sk_sid = sksec->sid; | 4042 | u32 sk_sid = sksec->sid; |
4033 | struct avc_audit_data ad; | 4043 | struct common_audit_data ad; |
4034 | char *addrp; | 4044 | char *addrp; |
4035 | 4045 | ||
4036 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4046 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4037 | ad.u.net.netif = skb->iif; | 4047 | ad.u.net.netif = skb->iif; |
4038 | ad.u.net.family = family; | 4048 | ad.u.net.family = family; |
4039 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4049 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4071,7 +4081,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4071 | struct sk_security_struct *sksec = sk->sk_security; | 4081 | struct sk_security_struct *sksec = sk->sk_security; |
4072 | u16 family = sk->sk_family; | 4082 | u16 family = sk->sk_family; |
4073 | u32 sk_sid = sksec->sid; | 4083 | u32 sk_sid = sksec->sid; |
4074 | struct avc_audit_data ad; | 4084 | struct common_audit_data ad; |
4075 | char *addrp; | 4085 | char *addrp; |
4076 | u8 secmark_active; | 4086 | u8 secmark_active; |
4077 | u8 peerlbl_active; | 4087 | u8 peerlbl_active; |
@@ -4095,7 +4105,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4095 | if (!secmark_active && !peerlbl_active) | 4105 | if (!secmark_active && !peerlbl_active) |
4096 | return 0; | 4106 | return 0; |
4097 | 4107 | ||
4098 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4108 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4099 | ad.u.net.netif = skb->iif; | 4109 | ad.u.net.netif = skb->iif; |
4100 | ad.u.net.family = family; | 4110 | ad.u.net.family = family; |
4101 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4111 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4353,7 +4363,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4353 | int err; | 4363 | int err; |
4354 | char *addrp; | 4364 | char *addrp; |
4355 | u32 peer_sid; | 4365 | u32 peer_sid; |
4356 | struct avc_audit_data ad; | 4366 | struct common_audit_data ad; |
4357 | u8 secmark_active; | 4367 | u8 secmark_active; |
4358 | u8 netlbl_active; | 4368 | u8 netlbl_active; |
4359 | u8 peerlbl_active; | 4369 | u8 peerlbl_active; |
@@ -4370,7 +4380,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4370 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4380 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4371 | return NF_DROP; | 4381 | return NF_DROP; |
4372 | 4382 | ||
4373 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4383 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4374 | ad.u.net.netif = ifindex; | 4384 | ad.u.net.netif = ifindex; |
4375 | ad.u.net.family = family; | 4385 | ad.u.net.family = family; |
4376 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4386 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
@@ -4458,7 +4468,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4458 | { | 4468 | { |
4459 | struct sock *sk = skb->sk; | 4469 | struct sock *sk = skb->sk; |
4460 | struct sk_security_struct *sksec; | 4470 | struct sk_security_struct *sksec; |
4461 | struct avc_audit_data ad; | 4471 | struct common_audit_data ad; |
4462 | char *addrp; | 4472 | char *addrp; |
4463 | u8 proto; | 4473 | u8 proto; |
4464 | 4474 | ||
@@ -4466,7 +4476,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4466 | return NF_ACCEPT; | 4476 | return NF_ACCEPT; |
4467 | sksec = sk->sk_security; | 4477 | sksec = sk->sk_security; |
4468 | 4478 | ||
4469 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4479 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4470 | ad.u.net.netif = ifindex; | 4480 | ad.u.net.netif = ifindex; |
4471 | ad.u.net.family = family; | 4481 | ad.u.net.family = family; |
4472 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4482 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
@@ -4490,7 +4500,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4490 | u32 secmark_perm; | 4500 | u32 secmark_perm; |
4491 | u32 peer_sid; | 4501 | u32 peer_sid; |
4492 | struct sock *sk; | 4502 | struct sock *sk; |
4493 | struct avc_audit_data ad; | 4503 | struct common_audit_data ad; |
4494 | char *addrp; | 4504 | char *addrp; |
4495 | u8 secmark_active; | 4505 | u8 secmark_active; |
4496 | u8 peerlbl_active; | 4506 | u8 peerlbl_active; |
@@ -4549,7 +4559,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4549 | secmark_perm = PACKET__SEND; | 4559 | secmark_perm = PACKET__SEND; |
4550 | } | 4560 | } |
4551 | 4561 | ||
4552 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4562 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4553 | ad.u.net.netif = ifindex; | 4563 | ad.u.net.netif = ifindex; |
4554 | ad.u.net.family = family; | 4564 | ad.u.net.family = family; |
4555 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4565 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
@@ -4619,13 +4629,13 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4619 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4629 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
4620 | { | 4630 | { |
4621 | int err; | 4631 | int err; |
4622 | struct avc_audit_data ad; | 4632 | struct common_audit_data ad; |
4623 | 4633 | ||
4624 | err = cap_netlink_recv(skb, capability); | 4634 | err = cap_netlink_recv(skb, capability); |
4625 | if (err) | 4635 | if (err) |
4626 | return err; | 4636 | return err; |
4627 | 4637 | ||
4628 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4638 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
4629 | ad.u.cap = capability; | 4639 | ad.u.cap = capability; |
4630 | 4640 | ||
4631 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, | 4641 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, |
@@ -4684,12 +4694,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4684 | u32 perms) | 4694 | u32 perms) |
4685 | { | 4695 | { |
4686 | struct ipc_security_struct *isec; | 4696 | struct ipc_security_struct *isec; |
4687 | struct avc_audit_data ad; | 4697 | struct common_audit_data ad; |
4688 | u32 sid = current_sid(); | 4698 | u32 sid = current_sid(); |
4689 | 4699 | ||
4690 | isec = ipc_perms->security; | 4700 | isec = ipc_perms->security; |
4691 | 4701 | ||
4692 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4702 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4693 | ad.u.ipc_id = ipc_perms->key; | 4703 | ad.u.ipc_id = ipc_perms->key; |
4694 | 4704 | ||
4695 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4705 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4709,7 +4719,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
4709 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4719 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4710 | { | 4720 | { |
4711 | struct ipc_security_struct *isec; | 4721 | struct ipc_security_struct *isec; |
4712 | struct avc_audit_data ad; | 4722 | struct common_audit_data ad; |
4713 | u32 sid = current_sid(); | 4723 | u32 sid = current_sid(); |
4714 | int rc; | 4724 | int rc; |
4715 | 4725 | ||
@@ -4719,7 +4729,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4719 | 4729 | ||
4720 | isec = msq->q_perm.security; | 4730 | isec = msq->q_perm.security; |
4721 | 4731 | ||
4722 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4732 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4723 | ad.u.ipc_id = msq->q_perm.key; | 4733 | ad.u.ipc_id = msq->q_perm.key; |
4724 | 4734 | ||
4725 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4735 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4739,12 +4749,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) | |||
4739 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4749 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4740 | { | 4750 | { |
4741 | struct ipc_security_struct *isec; | 4751 | struct ipc_security_struct *isec; |
4742 | struct avc_audit_data ad; | 4752 | struct common_audit_data ad; |
4743 | u32 sid = current_sid(); | 4753 | u32 sid = current_sid(); |
4744 | 4754 | ||
4745 | isec = msq->q_perm.security; | 4755 | isec = msq->q_perm.security; |
4746 | 4756 | ||
4747 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4757 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4748 | ad.u.ipc_id = msq->q_perm.key; | 4758 | ad.u.ipc_id = msq->q_perm.key; |
4749 | 4759 | ||
4750 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4760 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4783,7 +4793,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4783 | { | 4793 | { |
4784 | struct ipc_security_struct *isec; | 4794 | struct ipc_security_struct *isec; |
4785 | struct msg_security_struct *msec; | 4795 | struct msg_security_struct *msec; |
4786 | struct avc_audit_data ad; | 4796 | struct common_audit_data ad; |
4787 | u32 sid = current_sid(); | 4797 | u32 sid = current_sid(); |
4788 | int rc; | 4798 | int rc; |
4789 | 4799 | ||
@@ -4804,7 +4814,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4804 | return rc; | 4814 | return rc; |
4805 | } | 4815 | } |
4806 | 4816 | ||
4807 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4817 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4808 | ad.u.ipc_id = msq->q_perm.key; | 4818 | ad.u.ipc_id = msq->q_perm.key; |
4809 | 4819 | ||
4810 | /* Can this process write to the queue? */ | 4820 | /* Can this process write to the queue? */ |
@@ -4828,14 +4838,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4828 | { | 4838 | { |
4829 | struct ipc_security_struct *isec; | 4839 | struct ipc_security_struct *isec; |
4830 | struct msg_security_struct *msec; | 4840 | struct msg_security_struct *msec; |
4831 | struct avc_audit_data ad; | 4841 | struct common_audit_data ad; |
4832 | u32 sid = task_sid(target); | 4842 | u32 sid = task_sid(target); |
4833 | int rc; | 4843 | int rc; |
4834 | 4844 | ||
4835 | isec = msq->q_perm.security; | 4845 | isec = msq->q_perm.security; |
4836 | msec = msg->security; | 4846 | msec = msg->security; |
4837 | 4847 | ||
4838 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4848 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4839 | ad.u.ipc_id = msq->q_perm.key; | 4849 | ad.u.ipc_id = msq->q_perm.key; |
4840 | 4850 | ||
4841 | rc = avc_has_perm(sid, isec->sid, | 4851 | rc = avc_has_perm(sid, isec->sid, |
@@ -4850,7 +4860,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4850 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4860 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4851 | { | 4861 | { |
4852 | struct ipc_security_struct *isec; | 4862 | struct ipc_security_struct *isec; |
4853 | struct avc_audit_data ad; | 4863 | struct common_audit_data ad; |
4854 | u32 sid = current_sid(); | 4864 | u32 sid = current_sid(); |
4855 | int rc; | 4865 | int rc; |
4856 | 4866 | ||
@@ -4860,7 +4870,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
4860 | 4870 | ||
4861 | isec = shp->shm_perm.security; | 4871 | isec = shp->shm_perm.security; |
4862 | 4872 | ||
4863 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4873 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4864 | ad.u.ipc_id = shp->shm_perm.key; | 4874 | ad.u.ipc_id = shp->shm_perm.key; |
4865 | 4875 | ||
4866 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4876 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4880,12 +4890,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
4880 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4890 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4881 | { | 4891 | { |
4882 | struct ipc_security_struct *isec; | 4892 | struct ipc_security_struct *isec; |
4883 | struct avc_audit_data ad; | 4893 | struct common_audit_data ad; |
4884 | u32 sid = current_sid(); | 4894 | u32 sid = current_sid(); |
4885 | 4895 | ||
4886 | isec = shp->shm_perm.security; | 4896 | isec = shp->shm_perm.security; |
4887 | 4897 | ||
4888 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4898 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4889 | ad.u.ipc_id = shp->shm_perm.key; | 4899 | ad.u.ipc_id = shp->shm_perm.key; |
4890 | 4900 | ||
4891 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4901 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4942,7 +4952,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
4942 | static int selinux_sem_alloc_security(struct sem_array *sma) | 4952 | static int selinux_sem_alloc_security(struct sem_array *sma) |
4943 | { | 4953 | { |
4944 | struct ipc_security_struct *isec; | 4954 | struct ipc_security_struct *isec; |
4945 | struct avc_audit_data ad; | 4955 | struct common_audit_data ad; |
4946 | u32 sid = current_sid(); | 4956 | u32 sid = current_sid(); |
4947 | int rc; | 4957 | int rc; |
4948 | 4958 | ||
@@ -4952,7 +4962,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
4952 | 4962 | ||
4953 | isec = sma->sem_perm.security; | 4963 | isec = sma->sem_perm.security; |
4954 | 4964 | ||
4955 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4965 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4956 | ad.u.ipc_id = sma->sem_perm.key; | 4966 | ad.u.ipc_id = sma->sem_perm.key; |
4957 | 4967 | ||
4958 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 4968 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -4972,12 +4982,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
4972 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 4982 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
4973 | { | 4983 | { |
4974 | struct ipc_security_struct *isec; | 4984 | struct ipc_security_struct *isec; |
4975 | struct avc_audit_data ad; | 4985 | struct common_audit_data ad; |
4976 | u32 sid = current_sid(); | 4986 | u32 sid = current_sid(); |
4977 | 4987 | ||
4978 | isec = sma->sem_perm.security; | 4988 | isec = sma->sem_perm.security; |
4979 | 4989 | ||
4980 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4990 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4981 | ad.u.ipc_id = sma->sem_perm.key; | 4991 | ad.u.ipc_id = sma->sem_perm.key; |
4982 | 4992 | ||
4983 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 4993 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5195,7 +5205,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5195 | 5205 | ||
5196 | /* Only allow single threaded processes to change context */ | 5206 | /* Only allow single threaded processes to change context */ |
5197 | error = -EPERM; | 5207 | error = -EPERM; |
5198 | if (!is_single_threaded(p)) { | 5208 | if (!current_is_single_threaded()) { |
5199 | error = security_bounded_transition(tsec->sid, sid); | 5209 | error = security_bounded_transition(tsec->sid, sid); |
5200 | if (error) | 5210 | if (error) |
5201 | goto abort_change; | 5211 | goto abort_change; |
@@ -5323,7 +5333,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5323 | static struct security_operations selinux_ops = { | 5333 | static struct security_operations selinux_ops = { |
5324 | .name = "selinux", | 5334 | .name = "selinux", |
5325 | 5335 | ||
5326 | .ptrace_may_access = selinux_ptrace_may_access, | 5336 | .ptrace_access_check = selinux_ptrace_access_check, |
5327 | .ptrace_traceme = selinux_ptrace_traceme, | 5337 | .ptrace_traceme = selinux_ptrace_traceme, |
5328 | .capget = selinux_capget, | 5338 | .capget = selinux_capget, |
5329 | .capset = selinux_capset, | 5339 | .capset = selinux_capset, |
@@ -5400,6 +5410,7 @@ static struct security_operations selinux_ops = { | |||
5400 | .cred_prepare = selinux_cred_prepare, | 5410 | .cred_prepare = selinux_cred_prepare, |
5401 | .kernel_act_as = selinux_kernel_act_as, | 5411 | .kernel_act_as = selinux_kernel_act_as, |
5402 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5412 | .kernel_create_files_as = selinux_kernel_create_files_as, |
5413 | .kernel_module_request = selinux_kernel_module_request, | ||
5403 | .task_setpgid = selinux_task_setpgid, | 5414 | .task_setpgid = selinux_task_setpgid, |
5404 | .task_getpgid = selinux_task_getpgid, | 5415 | .task_getpgid = selinux_task_getpgid, |
5405 | .task_getsid = selinux_task_getsid, | 5416 | .task_getsid = selinux_task_getsid, |
@@ -5691,6 +5702,9 @@ int selinux_disable(void) | |||
5691 | selinux_disabled = 1; | 5702 | selinux_disabled = 1; |
5692 | selinux_enabled = 0; | 5703 | selinux_enabled = 0; |
5693 | 5704 | ||
5705 | /* Try to destroy the avc node cache */ | ||
5706 | avc_disable(); | ||
5707 | |||
5694 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5708 | /* Reset security_ops to the secondary module, dummy or capability. */ |
5695 | security_ops = secondary_ops; | 5709 | security_ops = secondary_ops; |
5696 | 5710 | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 31df1d7c1aee..2b683ad83d21 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
@@ -107,6 +107,7 @@ | |||
107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") | 107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") |
108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") | 108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") |
109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") | 109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") |
110 | S_(SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, "module_request") | ||
110 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") | 111 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") |
111 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") | 112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") |
112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") | 113 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") |
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index d645192ee950..21c722669902 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
@@ -508,6 +508,7 @@ | |||
508 | #define SYSTEM__SYSLOG_READ 0x00000002UL | 508 | #define SYSTEM__SYSLOG_READ 0x00000002UL |
509 | #define SYSTEM__SYSLOG_MOD 0x00000004UL | 509 | #define SYSTEM__SYSLOG_MOD 0x00000004UL |
510 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL | 510 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL |
511 | #define SYSTEM__MODULE_REQUEST 0x00000010UL | ||
511 | #define CAPABILITY__CHOWN 0x00000001UL | 512 | #define CAPABILITY__CHOWN 0x00000001UL |
512 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL | 513 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL |
513 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL | 514 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index d12ff1a9c0aa..e94e82f73818 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/audit.h> | 15 | #include <linux/audit.h> |
16 | #include <linux/lsm_audit.h> | ||
16 | #include <linux/in6.h> | 17 | #include <linux/in6.h> |
17 | #include <linux/path.h> | 18 | #include <linux/path.h> |
18 | #include <asm/system.h> | 19 | #include <asm/system.h> |
@@ -36,48 +37,6 @@ struct inode; | |||
36 | struct sock; | 37 | struct sock; |
37 | struct sk_buff; | 38 | struct sk_buff; |
38 | 39 | ||
39 | /* Auxiliary data to use in generating the audit record. */ | ||
40 | struct avc_audit_data { | ||
41 | char type; | ||
42 | #define AVC_AUDIT_DATA_FS 1 | ||
43 | #define AVC_AUDIT_DATA_NET 2 | ||
44 | #define AVC_AUDIT_DATA_CAP 3 | ||
45 | #define AVC_AUDIT_DATA_IPC 4 | ||
46 | struct task_struct *tsk; | ||
47 | union { | ||
48 | struct { | ||
49 | struct path path; | ||
50 | struct inode *inode; | ||
51 | } fs; | ||
52 | struct { | ||
53 | int netif; | ||
54 | struct sock *sk; | ||
55 | u16 family; | ||
56 | __be16 dport; | ||
57 | __be16 sport; | ||
58 | union { | ||
59 | struct { | ||
60 | __be32 daddr; | ||
61 | __be32 saddr; | ||
62 | } v4; | ||
63 | struct { | ||
64 | struct in6_addr daddr; | ||
65 | struct in6_addr saddr; | ||
66 | } v6; | ||
67 | } fam; | ||
68 | } net; | ||
69 | int cap; | ||
70 | int ipc_id; | ||
71 | } u; | ||
72 | }; | ||
73 | |||
74 | #define v4info fam.v4 | ||
75 | #define v6info fam.v6 | ||
76 | |||
77 | /* Initialize an AVC audit data structure. */ | ||
78 | #define AVC_AUDIT_DATA_INIT(_d,_t) \ | ||
79 | { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } | ||
80 | |||
81 | /* | 40 | /* |
82 | * AVC statistics | 41 | * AVC statistics |
83 | */ | 42 | */ |
@@ -98,7 +57,9 @@ void __init avc_init(void); | |||
98 | 57 | ||
99 | void avc_audit(u32 ssid, u32 tsid, | 58 | void avc_audit(u32 ssid, u32 tsid, |
100 | u16 tclass, u32 requested, | 59 | u16 tclass, u32 requested, |
101 | struct av_decision *avd, int result, struct avc_audit_data *auditdata); | 60 | struct av_decision *avd, |
61 | int result, | ||
62 | struct common_audit_data *a); | ||
102 | 63 | ||
103 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 64 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
104 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 65 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
@@ -108,7 +69,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
108 | 69 | ||
109 | int avc_has_perm(u32 ssid, u32 tsid, | 70 | int avc_has_perm(u32 ssid, u32 tsid, |
110 | u16 tclass, u32 requested, | 71 | u16 tclass, u32 requested, |
111 | struct avc_audit_data *auditdata); | 72 | struct common_audit_data *auditdata); |
112 | 73 | ||
113 | u32 avc_policy_seqno(void); | 74 | u32 avc_policy_seqno(void); |
114 | 75 | ||
@@ -127,13 +88,13 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
127 | u32 events, u32 ssid, u32 tsid, | 88 | u32 events, u32 ssid, u32 tsid, |
128 | u16 tclass, u32 perms); | 89 | u16 tclass, u32 perms); |
129 | 90 | ||
130 | /* Shows permission in human readable form */ | ||
131 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); | ||
132 | |||
133 | /* Exported to selinuxfs */ | 91 | /* Exported to selinuxfs */ |
134 | int avc_get_hash_stats(char *page); | 92 | int avc_get_hash_stats(char *page); |
135 | extern unsigned int avc_cache_threshold; | 93 | extern unsigned int avc_cache_threshold; |
136 | 94 | ||
95 | /* Attempt to free avc node cache */ | ||
96 | void avc_disable(void); | ||
97 | |||
137 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 98 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
138 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); | 99 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); |
139 | #endif | 100 | #endif |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index b4b5b9b2f0be..8d7384280a7a 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
@@ -59,7 +59,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); | |||
59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
60 | struct sk_buff *skb, | 60 | struct sk_buff *skb, |
61 | u16 family, | 61 | u16 family, |
62 | struct avc_audit_data *ad); | 62 | struct common_audit_data *ad); |
63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | 63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, |
64 | int level, | 64 | int level, |
65 | int optname); | 65 | int optname); |
@@ -129,7 +129,7 @@ static inline int selinux_netlbl_socket_post_create(struct sock *sk, | |||
129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
130 | struct sk_buff *skb, | 130 | struct sk_buff *skb, |
131 | u16 family, | 131 | u16 family, |
132 | struct avc_audit_data *ad) | 132 | struct common_audit_data *ad) |
133 | { | 133 | { |
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 289e24b39e3e..13128f9a3e5a 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -41,9 +41,9 @@ static inline int selinux_xfrm_enabled(void) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, | 43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, |
44 | struct avc_audit_data *ad); | 44 | struct common_audit_data *ad); |
45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
46 | struct avc_audit_data *ad, u8 proto); | 46 | struct common_audit_data *ad, u8 proto); |
47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
48 | 48 | ||
49 | static inline void selinux_xfrm_notify_policyload(void) | 49 | static inline void selinux_xfrm_notify_policyload(void) |
@@ -57,13 +57,13 @@ static inline int selinux_xfrm_enabled(void) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
60 | struct avc_audit_data *ad) | 60 | struct common_audit_data *ad) |
61 | { | 61 | { |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
66 | struct avc_audit_data *ad, u8 proto) | 66 | struct common_audit_data *ad, u8 proto) |
67 | { | 67 | { |
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2e984413c7b2..e68823741ad5 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -342,7 +342,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) | |||
342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
343 | struct sk_buff *skb, | 343 | struct sk_buff *skb, |
344 | u16 family, | 344 | u16 family, |
345 | struct avc_audit_data *ad) | 345 | struct common_audit_data *ad) |
346 | { | 346 | { |
347 | int rc; | 347 | int rc; |
348 | u32 nlbl_sid; | 348 | u32 nlbl_sid; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 500e6f78e115..ff17820d35ec 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -22,6 +22,11 @@ | |||
22 | * | 22 | * |
23 | * Added validation of kernel classes and permissions | 23 | * Added validation of kernel classes and permissions |
24 | * | 24 | * |
25 | * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
26 | * | ||
27 | * Added support for bounds domain and audit messaged on masked permissions | ||
28 | * | ||
29 | * Copyright (C) 2008, 2009 NEC Corporation | ||
25 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
26 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC | 32 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
@@ -279,6 +284,95 @@ mls_ops: | |||
279 | } | 284 | } |
280 | 285 | ||
281 | /* | 286 | /* |
287 | * security_dump_masked_av - dumps masked permissions during | ||
288 | * security_compute_av due to RBAC, MLS/Constraint and Type bounds. | ||
289 | */ | ||
290 | static int dump_masked_av_helper(void *k, void *d, void *args) | ||
291 | { | ||
292 | struct perm_datum *pdatum = d; | ||
293 | char **permission_names = args; | ||
294 | |||
295 | BUG_ON(pdatum->value < 1 || pdatum->value > 32); | ||
296 | |||
297 | permission_names[pdatum->value - 1] = (char *)k; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static void security_dump_masked_av(struct context *scontext, | ||
303 | struct context *tcontext, | ||
304 | u16 tclass, | ||
305 | u32 permissions, | ||
306 | const char *reason) | ||
307 | { | ||
308 | struct common_datum *common_dat; | ||
309 | struct class_datum *tclass_dat; | ||
310 | struct audit_buffer *ab; | ||
311 | char *tclass_name; | ||
312 | char *scontext_name = NULL; | ||
313 | char *tcontext_name = NULL; | ||
314 | char *permission_names[32]; | ||
315 | int index, length; | ||
316 | bool need_comma = false; | ||
317 | |||
318 | if (!permissions) | ||
319 | return; | ||
320 | |||
321 | tclass_name = policydb.p_class_val_to_name[tclass - 1]; | ||
322 | tclass_dat = policydb.class_val_to_struct[tclass - 1]; | ||
323 | common_dat = tclass_dat->comdatum; | ||
324 | |||
325 | /* init permission_names */ | ||
326 | if (common_dat && | ||
327 | hashtab_map(common_dat->permissions.table, | ||
328 | dump_masked_av_helper, permission_names) < 0) | ||
329 | goto out; | ||
330 | |||
331 | if (hashtab_map(tclass_dat->permissions.table, | ||
332 | dump_masked_av_helper, permission_names) < 0) | ||
333 | goto out; | ||
334 | |||
335 | /* get scontext/tcontext in text form */ | ||
336 | if (context_struct_to_string(scontext, | ||
337 | &scontext_name, &length) < 0) | ||
338 | goto out; | ||
339 | |||
340 | if (context_struct_to_string(tcontext, | ||
341 | &tcontext_name, &length) < 0) | ||
342 | goto out; | ||
343 | |||
344 | /* audit a message */ | ||
345 | ab = audit_log_start(current->audit_context, | ||
346 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
347 | if (!ab) | ||
348 | goto out; | ||
349 | |||
350 | audit_log_format(ab, "op=security_compute_av reason=%s " | ||
351 | "scontext=%s tcontext=%s tclass=%s perms=", | ||
352 | reason, scontext_name, tcontext_name, tclass_name); | ||
353 | |||
354 | for (index = 0; index < 32; index++) { | ||
355 | u32 mask = (1 << index); | ||
356 | |||
357 | if ((mask & permissions) == 0) | ||
358 | continue; | ||
359 | |||
360 | audit_log_format(ab, "%s%s", | ||
361 | need_comma ? "," : "", | ||
362 | permission_names[index] | ||
363 | ? permission_names[index] : "????"); | ||
364 | need_comma = true; | ||
365 | } | ||
366 | audit_log_end(ab); | ||
367 | out: | ||
368 | /* release scontext/tcontext */ | ||
369 | kfree(tcontext_name); | ||
370 | kfree(scontext_name); | ||
371 | |||
372 | return; | ||
373 | } | ||
374 | |||
375 | /* | ||
282 | * security_boundary_permission - drops violated permissions | 376 | * security_boundary_permission - drops violated permissions |
283 | * on boundary constraint. | 377 | * on boundary constraint. |
284 | */ | 378 | */ |
@@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
347 | } | 441 | } |
348 | 442 | ||
349 | if (masked) { | 443 | if (masked) { |
350 | struct audit_buffer *ab; | ||
351 | char *stype_name | ||
352 | = policydb.p_type_val_to_name[source->value - 1]; | ||
353 | char *ttype_name | ||
354 | = policydb.p_type_val_to_name[target->value - 1]; | ||
355 | char *tclass_name | ||
356 | = policydb.p_class_val_to_name[tclass - 1]; | ||
357 | |||
358 | /* mask violated permissions */ | 444 | /* mask violated permissions */ |
359 | avd->allowed &= ~masked; | 445 | avd->allowed &= ~masked; |
360 | 446 | ||
361 | /* notice to userspace via audit message */ | 447 | /* audit masked permissions */ |
362 | ab = audit_log_start(current->audit_context, | 448 | security_dump_masked_av(scontext, tcontext, |
363 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | 449 | tclass, masked, "bounds"); |
364 | if (!ab) | ||
365 | return; | ||
366 | |||
367 | audit_log_format(ab, "av boundary violation: " | ||
368 | "source=%s target=%s tclass=%s", | ||
369 | stype_name, ttype_name, tclass_name); | ||
370 | avc_dump_av(ab, tclass, masked); | ||
371 | audit_log_end(ab); | ||
372 | } | 450 | } |
373 | } | 451 | } |
374 | 452 | ||
@@ -480,7 +558,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
480 | if ((constraint->permissions & (avd->allowed)) && | 558 | if ((constraint->permissions & (avd->allowed)) && |
481 | !constraint_expr_eval(scontext, tcontext, NULL, | 559 | !constraint_expr_eval(scontext, tcontext, NULL, |
482 | constraint->expr)) { | 560 | constraint->expr)) { |
483 | avd->allowed = (avd->allowed) & ~(constraint->permissions); | 561 | avd->allowed &= ~(constraint->permissions); |
484 | } | 562 | } |
485 | constraint = constraint->next; | 563 | constraint = constraint->next; |
486 | } | 564 | } |
@@ -499,8 +577,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
499 | break; | 577 | break; |
500 | } | 578 | } |
501 | if (!ra) | 579 | if (!ra) |
502 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | | 580 | avd->allowed &= ~(PROCESS__TRANSITION | |
503 | PROCESS__DYNTRANSITION); | 581 | PROCESS__DYNTRANSITION); |
504 | } | 582 | } |
505 | 583 | ||
506 | /* | 584 | /* |
@@ -687,6 +765,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
687 | } | 765 | } |
688 | index = type->bounds; | 766 | index = type->bounds; |
689 | } | 767 | } |
768 | |||
769 | if (rc) { | ||
770 | char *old_name = NULL; | ||
771 | char *new_name = NULL; | ||
772 | int length; | ||
773 | |||
774 | if (!context_struct_to_string(old_context, | ||
775 | &old_name, &length) && | ||
776 | !context_struct_to_string(new_context, | ||
777 | &new_name, &length)) { | ||
778 | audit_log(current->audit_context, | ||
779 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
780 | "op=security_bounded_transition " | ||
781 | "result=denied " | ||
782 | "oldcontext=%s newcontext=%s", | ||
783 | old_name, new_name); | ||
784 | } | ||
785 | kfree(new_name); | ||
786 | kfree(old_name); | ||
787 | } | ||
690 | out: | 788 | out: |
691 | read_unlock(&policy_rwlock); | 789 | read_unlock(&policy_rwlock); |
692 | 790 | ||
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 72b18452e1a1..f3cb9ed731a9 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -401,7 +401,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) | |||
401 | * gone thru the IPSec process. | 401 | * gone thru the IPSec process. |
402 | */ | 402 | */ |
403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
404 | struct avc_audit_data *ad) | 404 | struct common_audit_data *ad) |
405 | { | 405 | { |
406 | int i, rc = 0; | 406 | int i, rc = 0; |
407 | struct sec_path *sp; | 407 | struct sec_path *sp; |
@@ -442,7 +442,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | |||
442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. | 442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. |
443 | */ | 443 | */ |
444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
445 | struct avc_audit_data *ad, u8 proto) | 445 | struct common_audit_data *ad, u8 proto) |
446 | { | 446 | { |
447 | struct dst_entry *dst; | 447 | struct dst_entry *dst; |
448 | int rc = 0; | 448 | int rc = 0; |