diff options
| author | David Howells <dhowells@redhat.com> | 2015-07-10 17:19:58 -0400 |
|---|---|---|
| committer | Paul Moore <pmoore@redhat.com> | 2015-07-13 13:31:59 -0400 |
| commit | c3c188b2c3ed29effe8693672ee1c84184103b4e (patch) | |
| tree | 54782e4ec8029c70b7acf0ad684a34b7b1e84b98 /security | |
| parent | bd1741f4cf05d7709348f591d16eeb5f786de673 (diff) | |
selinux: Create a common helper to determine an inode label [ver #3]
Create a common helper function to determine the label for a new inode.
This is then used by:
- may_create()
- selinux_dentry_init_security()
- selinux_inode_init_security()
This will change the behaviour of the functions slightly, bringing them
all into line.
Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'security')
| -rw-r--r-- | security/selinux/hooks.c | 87 |
1 files changed, 41 insertions, 46 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ef310f82717d..f4be0a110788 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -1709,6 +1709,32 @@ out: | |||
| 1709 | return rc; | 1709 | return rc; |
| 1710 | } | 1710 | } |
| 1711 | 1711 | ||
| 1712 | /* | ||
| 1713 | * Determine the label for an inode that might be unioned. | ||
| 1714 | */ | ||
| 1715 | static int selinux_determine_inode_label(const struct inode *dir, | ||
| 1716 | const struct qstr *name, | ||
| 1717 | u16 tclass, | ||
| 1718 | u32 *_new_isid) | ||
| 1719 | { | ||
| 1720 | const struct superblock_security_struct *sbsec = dir->i_sb->s_security; | ||
| 1721 | const struct inode_security_struct *dsec = dir->i_security; | ||
| 1722 | const struct task_security_struct *tsec = current_security(); | ||
| 1723 | |||
| 1724 | if ((sbsec->flags & SE_SBINITIALIZED) && | ||
| 1725 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) { | ||
| 1726 | *_new_isid = sbsec->mntpoint_sid; | ||
| 1727 | } else if ((sbsec->flags & SBLABEL_MNT) && | ||
| 1728 | tsec->create_sid) { | ||
| 1729 | *_new_isid = tsec->create_sid; | ||
| 1730 | } else { | ||
| 1731 | return security_transition_sid(tsec->sid, dsec->sid, tclass, | ||
| 1732 | name, _new_isid); | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | return 0; | ||
| 1736 | } | ||
| 1737 | |||
| 1712 | /* Check whether a task can create a file. */ | 1738 | /* Check whether a task can create a file. */ |
| 1713 | static int may_create(struct inode *dir, | 1739 | static int may_create(struct inode *dir, |
| 1714 | struct dentry *dentry, | 1740 | struct dentry *dentry, |
| @@ -1725,7 +1751,6 @@ static int may_create(struct inode *dir, | |||
| 1725 | sbsec = dir->i_sb->s_security; | 1751 | sbsec = dir->i_sb->s_security; |
| 1726 | 1752 | ||
| 1727 | sid = tsec->sid; | 1753 | sid = tsec->sid; |
| 1728 | newsid = tsec->create_sid; | ||
| 1729 | 1754 | ||
| 1730 | ad.type = LSM_AUDIT_DATA_DENTRY; | 1755 | ad.type = LSM_AUDIT_DATA_DENTRY; |
| 1731 | ad.u.dentry = dentry; | 1756 | ad.u.dentry = dentry; |
| @@ -1736,12 +1761,10 @@ static int may_create(struct inode *dir, | |||
| 1736 | if (rc) | 1761 | if (rc) |
| 1737 | return rc; | 1762 | return rc; |
| 1738 | 1763 | ||
| 1739 | if (!newsid || !(sbsec->flags & SBLABEL_MNT)) { | 1764 | rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass, |
| 1740 | rc = security_transition_sid(sid, dsec->sid, tclass, | 1765 | &newsid); |
| 1741 | &dentry->d_name, &newsid); | 1766 | if (rc) |
| 1742 | if (rc) | 1767 | return rc; |
| 1743 | return rc; | ||
| 1744 | } | ||
| 1745 | 1768 | ||
| 1746 | rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); | 1769 | rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); |
| 1747 | if (rc) | 1770 | if (rc) |
| @@ -2715,32 +2738,14 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode, | |||
| 2715 | struct qstr *name, void **ctx, | 2738 | struct qstr *name, void **ctx, |
| 2716 | u32 *ctxlen) | 2739 | u32 *ctxlen) |
| 2717 | { | 2740 | { |
| 2718 | const struct cred *cred = current_cred(); | ||
| 2719 | struct task_security_struct *tsec; | ||
| 2720 | struct inode_security_struct *dsec; | ||
| 2721 | struct superblock_security_struct *sbsec; | ||
| 2722 | struct inode *dir = d_backing_inode(dentry->d_parent); | ||
| 2723 | u32 newsid; | 2741 | u32 newsid; |
| 2724 | int rc; | 2742 | int rc; |
| 2725 | 2743 | ||
| 2726 | tsec = cred->security; | 2744 | rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name, |
| 2727 | dsec = dir->i_security; | 2745 | inode_mode_to_security_class(mode), |
| 2728 | sbsec = dir->i_sb->s_security; | 2746 | &newsid); |
| 2729 | 2747 | if (rc) | |
| 2730 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | 2748 | return rc; |
| 2731 | newsid = tsec->create_sid; | ||
| 2732 | } else { | ||
| 2733 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
| 2734 | inode_mode_to_security_class(mode), | ||
| 2735 | name, | ||
| 2736 | &newsid); | ||
| 2737 | if (rc) { | ||
| 2738 | printk(KERN_WARNING | ||
| 2739 | "%s: security_transition_sid failed, rc=%d\n", | ||
| 2740 | __func__, -rc); | ||
| 2741 | return rc; | ||
| 2742 | } | ||
| 2743 | } | ||
| 2744 | 2749 | ||
| 2745 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); | 2750 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); |
| 2746 | } | 2751 | } |
| @@ -2763,22 +2768,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2763 | sid = tsec->sid; | 2768 | sid = tsec->sid; |
| 2764 | newsid = tsec->create_sid; | 2769 | newsid = tsec->create_sid; |
| 2765 | 2770 | ||
| 2766 | if ((sbsec->flags & SE_SBINITIALIZED) && | 2771 | rc = selinux_determine_inode_label( |
| 2767 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) | 2772 | dir, qstr, |
| 2768 | newsid = sbsec->mntpoint_sid; | 2773 | inode_mode_to_security_class(inode->i_mode), |
| 2769 | else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) { | 2774 | &newsid); |
| 2770 | rc = security_transition_sid(sid, dsec->sid, | 2775 | if (rc) |
| 2771 | inode_mode_to_security_class(inode->i_mode), | 2776 | return rc; |
| 2772 | qstr, &newsid); | ||
| 2773 | if (rc) { | ||
| 2774 | printk(KERN_WARNING "%s: " | ||
| 2775 | "security_transition_sid failed, rc=%d (dev=%s " | ||
| 2776 | "ino=%ld)\n", | ||
| 2777 | __func__, | ||
| 2778 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 2779 | return rc; | ||
| 2780 | } | ||
| 2781 | } | ||
| 2782 | 2777 | ||
| 2783 | /* Possibly defer initialization to selinux_complete_init. */ | 2778 | /* Possibly defer initialization to selinux_complete_init. */ |
| 2784 | if (sbsec->flags & SE_SBINITIALIZED) { | 2779 | if (sbsec->flags & SE_SBINITIALIZED) { |
