diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2015-12-24 11:09:39 -0500 |
---|---|---|
committer | Paul Moore <pmoore@redhat.com> | 2015-12-24 11:09:39 -0500 |
commit | 83da53c5a34564a0a63b26f84293c6e2a639e1e4 (patch) | |
tree | 67ac0a9d8c404f0a010e5398a07c9359ee7a2b5d | |
parent | d6335d77a7622a88380f3f207cc1f727f878dd21 (diff) |
selinux: Add accessor functions for inode->i_security
Add functions dentry_security and inode_security for accessing
inode->i_security. These functions initially don't do much, but they
will later be used to revalidate the security labels when necessary.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <pmoore@redhat.com>
-rw-r--r-- | security/selinux/hooks.c | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 19a8f1500a7e..1dc0d79a6a25 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -242,6 +242,24 @@ static int inode_alloc_security(struct inode *inode) | |||
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | /* | ||
246 | * Get the security label of an inode. | ||
247 | */ | ||
248 | static struct inode_security_struct *inode_security(struct inode *inode) | ||
249 | { | ||
250 | return inode->i_security; | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * Get the security label of a dentry's backing inode. | ||
255 | */ | ||
256 | static struct inode_security_struct *backing_inode_security(struct dentry *dentry) | ||
257 | { | ||
258 | struct inode *inode = d_backing_inode(dentry); | ||
259 | |||
260 | return inode->i_security; | ||
261 | } | ||
262 | |||
245 | static void inode_free_rcu(struct rcu_head *head) | 263 | static void inode_free_rcu(struct rcu_head *head) |
246 | { | 264 | { |
247 | struct inode_security_struct *isec; | 265 | struct inode_security_struct *isec; |
@@ -565,8 +583,8 @@ static int selinux_get_mnt_opts(const struct super_block *sb, | |||
565 | opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; | 583 | opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; |
566 | } | 584 | } |
567 | if (sbsec->flags & ROOTCONTEXT_MNT) { | 585 | if (sbsec->flags & ROOTCONTEXT_MNT) { |
568 | struct inode *root = d_backing_inode(sbsec->sb->s_root); | 586 | struct dentry *root = sbsec->sb->s_root; |
569 | struct inode_security_struct *isec = root->i_security; | 587 | struct inode_security_struct *isec = backing_inode_security(root); |
570 | 588 | ||
571 | rc = security_sid_to_context(isec->sid, &context, &len); | 589 | rc = security_sid_to_context(isec->sid, &context, &len); |
572 | if (rc) | 590 | if (rc) |
@@ -621,8 +639,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
621 | int rc = 0, i; | 639 | int rc = 0, i; |
622 | struct superblock_security_struct *sbsec = sb->s_security; | 640 | struct superblock_security_struct *sbsec = sb->s_security; |
623 | const char *name = sb->s_type->name; | 641 | const char *name = sb->s_type->name; |
624 | struct inode *inode = d_backing_inode(sbsec->sb->s_root); | 642 | struct dentry *root = sbsec->sb->s_root; |
625 | struct inode_security_struct *root_isec = inode->i_security; | 643 | struct inode_security_struct *root_isec = backing_inode_security(root); |
626 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | 644 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; |
627 | u32 defcontext_sid = 0; | 645 | u32 defcontext_sid = 0; |
628 | char **mount_options = opts->mnt_opts; | 646 | char **mount_options = opts->mnt_opts; |
@@ -852,8 +870,8 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb, | |||
852 | if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid) | 870 | if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid) |
853 | goto mismatch; | 871 | goto mismatch; |
854 | if (oldflags & ROOTCONTEXT_MNT) { | 872 | if (oldflags & ROOTCONTEXT_MNT) { |
855 | struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security; | 873 | struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root); |
856 | struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security; | 874 | struct inode_security_struct *newroot = backing_inode_security(newsb->s_root); |
857 | if (oldroot->sid != newroot->sid) | 875 | if (oldroot->sid != newroot->sid) |
858 | goto mismatch; | 876 | goto mismatch; |
859 | } | 877 | } |
@@ -903,17 +921,14 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
903 | if (!set_fscontext) | 921 | if (!set_fscontext) |
904 | newsbsec->sid = sid; | 922 | newsbsec->sid = sid; |
905 | if (!set_rootcontext) { | 923 | if (!set_rootcontext) { |
906 | struct inode *newinode = d_backing_inode(newsb->s_root); | 924 | struct inode_security_struct *newisec = backing_inode_security(newsb->s_root); |
907 | struct inode_security_struct *newisec = newinode->i_security; | ||
908 | newisec->sid = sid; | 925 | newisec->sid = sid; |
909 | } | 926 | } |
910 | newsbsec->mntpoint_sid = sid; | 927 | newsbsec->mntpoint_sid = sid; |
911 | } | 928 | } |
912 | if (set_rootcontext) { | 929 | if (set_rootcontext) { |
913 | const struct inode *oldinode = d_backing_inode(oldsb->s_root); | 930 | const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root); |
914 | const struct inode_security_struct *oldisec = oldinode->i_security; | 931 | struct inode_security_struct *newisec = backing_inode_security(newsb->s_root); |
915 | struct inode *newinode = d_backing_inode(newsb->s_root); | ||
916 | struct inode_security_struct *newisec = newinode->i_security; | ||
917 | 932 | ||
918 | newisec->sid = oldisec->sid; | 933 | newisec->sid = oldisec->sid; |
919 | } | 934 | } |
@@ -1712,13 +1727,13 @@ out: | |||
1712 | /* | 1727 | /* |
1713 | * Determine the label for an inode that might be unioned. | 1728 | * Determine the label for an inode that might be unioned. |
1714 | */ | 1729 | */ |
1715 | static int selinux_determine_inode_label(const struct inode *dir, | 1730 | static int selinux_determine_inode_label(struct inode *dir, |
1716 | const struct qstr *name, | 1731 | const struct qstr *name, |
1717 | u16 tclass, | 1732 | u16 tclass, |
1718 | u32 *_new_isid) | 1733 | u32 *_new_isid) |
1719 | { | 1734 | { |
1720 | const struct superblock_security_struct *sbsec = dir->i_sb->s_security; | 1735 | const struct superblock_security_struct *sbsec = dir->i_sb->s_security; |
1721 | const struct inode_security_struct *dsec = dir->i_security; | 1736 | const struct inode_security_struct *dsec = inode_security(dir); |
1722 | const struct task_security_struct *tsec = current_security(); | 1737 | const struct task_security_struct *tsec = current_security(); |
1723 | 1738 | ||
1724 | if ((sbsec->flags & SE_SBINITIALIZED) && | 1739 | if ((sbsec->flags & SE_SBINITIALIZED) && |
@@ -1747,7 +1762,7 @@ static int may_create(struct inode *dir, | |||
1747 | struct common_audit_data ad; | 1762 | struct common_audit_data ad; |
1748 | int rc; | 1763 | int rc; |
1749 | 1764 | ||
1750 | dsec = dir->i_security; | 1765 | dsec = inode_security(dir); |
1751 | sbsec = dir->i_sb->s_security; | 1766 | sbsec = dir->i_sb->s_security; |
1752 | 1767 | ||
1753 | sid = tsec->sid; | 1768 | sid = tsec->sid; |
@@ -1800,8 +1815,8 @@ static int may_link(struct inode *dir, | |||
1800 | u32 av; | 1815 | u32 av; |
1801 | int rc; | 1816 | int rc; |
1802 | 1817 | ||
1803 | dsec = dir->i_security; | 1818 | dsec = inode_security(dir); |
1804 | isec = d_backing_inode(dentry)->i_security; | 1819 | isec = backing_inode_security(dentry); |
1805 | 1820 | ||
1806 | ad.type = LSM_AUDIT_DATA_DENTRY; | 1821 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1807 | ad.u.dentry = dentry; | 1822 | ad.u.dentry = dentry; |
@@ -1844,10 +1859,10 @@ static inline int may_rename(struct inode *old_dir, | |||
1844 | int old_is_dir, new_is_dir; | 1859 | int old_is_dir, new_is_dir; |
1845 | int rc; | 1860 | int rc; |
1846 | 1861 | ||
1847 | old_dsec = old_dir->i_security; | 1862 | old_dsec = inode_security(old_dir); |
1848 | old_isec = d_backing_inode(old_dentry)->i_security; | 1863 | old_isec = backing_inode_security(old_dentry); |
1849 | old_is_dir = d_is_dir(old_dentry); | 1864 | old_is_dir = d_is_dir(old_dentry); |
1850 | new_dsec = new_dir->i_security; | 1865 | new_dsec = inode_security(new_dir); |
1851 | 1866 | ||
1852 | ad.type = LSM_AUDIT_DATA_DENTRY; | 1867 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1853 | 1868 | ||
@@ -1875,7 +1890,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1875 | if (rc) | 1890 | if (rc) |
1876 | return rc; | 1891 | return rc; |
1877 | if (d_is_positive(new_dentry)) { | 1892 | if (d_is_positive(new_dentry)) { |
1878 | new_isec = d_backing_inode(new_dentry)->i_security; | 1893 | new_isec = backing_inode_security(new_dentry); |
1879 | new_is_dir = d_is_dir(new_dentry); | 1894 | new_is_dir = d_is_dir(new_dentry); |
1880 | rc = avc_has_perm(sid, new_isec->sid, | 1895 | rc = avc_has_perm(sid, new_isec->sid, |
1881 | new_isec->sclass, | 1896 | new_isec->sclass, |
@@ -2011,8 +2026,8 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2011 | { | 2026 | { |
2012 | u32 sid = task_sid(to); | 2027 | u32 sid = task_sid(to); |
2013 | struct file_security_struct *fsec = file->f_security; | 2028 | struct file_security_struct *fsec = file->f_security; |
2014 | struct inode *inode = d_backing_inode(file->f_path.dentry); | 2029 | struct dentry *dentry = file->f_path.dentry; |
2015 | struct inode_security_struct *isec = inode->i_security; | 2030 | struct inode_security_struct *isec = backing_inode_security(dentry); |
2016 | struct common_audit_data ad; | 2031 | struct common_audit_data ad; |
2017 | int rc; | 2032 | int rc; |
2018 | 2033 | ||
@@ -2028,7 +2043,7 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
2028 | return rc; | 2043 | return rc; |
2029 | } | 2044 | } |
2030 | 2045 | ||
2031 | if (unlikely(IS_PRIVATE(inode))) | 2046 | if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) |
2032 | return 0; | 2047 | return 0; |
2033 | 2048 | ||
2034 | return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), | 2049 | return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file), |
@@ -2217,7 +2232,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2217 | 2232 | ||
2218 | old_tsec = current_security(); | 2233 | old_tsec = current_security(); |
2219 | new_tsec = bprm->cred->security; | 2234 | new_tsec = bprm->cred->security; |
2220 | isec = inode->i_security; | 2235 | isec = inode_security(inode); |
2221 | 2236 | ||
2222 | /* Default to the current task SID. */ | 2237 | /* Default to the current task SID. */ |
2223 | new_tsec->sid = old_tsec->sid; | 2238 | new_tsec->sid = old_tsec->sid; |
@@ -2639,7 +2654,7 @@ static int selinux_sb_remount(struct super_block *sb, void *data) | |||
2639 | break; | 2654 | break; |
2640 | case ROOTCONTEXT_MNT: { | 2655 | case ROOTCONTEXT_MNT: { |
2641 | struct inode_security_struct *root_isec; | 2656 | struct inode_security_struct *root_isec; |
2642 | root_isec = d_backing_inode(sb->s_root)->i_security; | 2657 | root_isec = backing_inode_security(sb->s_root); |
2643 | 2658 | ||
2644 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) | 2659 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) |
2645 | goto out_bad_option; | 2660 | goto out_bad_option; |
@@ -2856,7 +2871,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode, | |||
2856 | ad.type = LSM_AUDIT_DATA_DENTRY; | 2871 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2857 | ad.u.dentry = dentry; | 2872 | ad.u.dentry = dentry; |
2858 | sid = cred_sid(cred); | 2873 | sid = cred_sid(cred); |
2859 | isec = inode->i_security; | 2874 | isec = inode_security(inode); |
2860 | 2875 | ||
2861 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad, | 2876 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad, |
2862 | rcu ? MAY_NOT_BLOCK : 0); | 2877 | rcu ? MAY_NOT_BLOCK : 0); |
@@ -2908,7 +2923,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
2908 | perms = file_mask_to_av(inode->i_mode, mask); | 2923 | perms = file_mask_to_av(inode->i_mode, mask); |
2909 | 2924 | ||
2910 | sid = cred_sid(cred); | 2925 | sid = cred_sid(cred); |
2911 | isec = inode->i_security; | 2926 | isec = inode_security(inode); |
2912 | 2927 | ||
2913 | rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); | 2928 | rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); |
2914 | audited = avc_audit_required(perms, &avd, rc, | 2929 | audited = avc_audit_required(perms, &avd, rc, |
@@ -2978,7 +2993,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2978 | const void *value, size_t size, int flags) | 2993 | const void *value, size_t size, int flags) |
2979 | { | 2994 | { |
2980 | struct inode *inode = d_backing_inode(dentry); | 2995 | struct inode *inode = d_backing_inode(dentry); |
2981 | struct inode_security_struct *isec = inode->i_security; | 2996 | struct inode_security_struct *isec = backing_inode_security(dentry); |
2982 | struct superblock_security_struct *sbsec; | 2997 | struct superblock_security_struct *sbsec; |
2983 | struct common_audit_data ad; | 2998 | struct common_audit_data ad; |
2984 | u32 newsid, sid = current_sid(); | 2999 | u32 newsid, sid = current_sid(); |
@@ -3055,7 +3070,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
3055 | int flags) | 3070 | int flags) |
3056 | { | 3071 | { |
3057 | struct inode *inode = d_backing_inode(dentry); | 3072 | struct inode *inode = d_backing_inode(dentry); |
3058 | struct inode_security_struct *isec = inode->i_security; | 3073 | struct inode_security_struct *isec = backing_inode_security(dentry); |
3059 | u32 newsid; | 3074 | u32 newsid; |
3060 | int rc; | 3075 | int rc; |
3061 | 3076 | ||
@@ -3113,7 +3128,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void | |||
3113 | u32 size; | 3128 | u32 size; |
3114 | int error; | 3129 | int error; |
3115 | char *context = NULL; | 3130 | char *context = NULL; |
3116 | struct inode_security_struct *isec = inode->i_security; | 3131 | struct inode_security_struct *isec = inode_security(inode); |
3117 | 3132 | ||
3118 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) | 3133 | if (strcmp(name, XATTR_SELINUX_SUFFIX)) |
3119 | return -EOPNOTSUPP; | 3134 | return -EOPNOTSUPP; |
@@ -3152,7 +3167,7 @@ out_nofree: | |||
3152 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, | 3167 | static int selinux_inode_setsecurity(struct inode *inode, const char *name, |
3153 | const void *value, size_t size, int flags) | 3168 | const void *value, size_t size, int flags) |
3154 | { | 3169 | { |
3155 | struct inode_security_struct *isec = inode->i_security; | 3170 | struct inode_security_struct *isec = inode_security(inode); |
3156 | u32 newsid; | 3171 | u32 newsid; |
3157 | int rc; | 3172 | int rc; |
3158 | 3173 | ||
@@ -3182,7 +3197,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t | |||
3182 | 3197 | ||
3183 | static void selinux_inode_getsecid(struct inode *inode, u32 *secid) | 3198 | static void selinux_inode_getsecid(struct inode *inode, u32 *secid) |
3184 | { | 3199 | { |
3185 | struct inode_security_struct *isec = inode->i_security; | 3200 | struct inode_security_struct *isec = inode_security(inode); |
3186 | *secid = isec->sid; | 3201 | *secid = isec->sid; |
3187 | } | 3202 | } |
3188 | 3203 | ||
@@ -3205,7 +3220,7 @@ static int selinux_file_permission(struct file *file, int mask) | |||
3205 | { | 3220 | { |
3206 | struct inode *inode = file_inode(file); | 3221 | struct inode *inode = file_inode(file); |
3207 | struct file_security_struct *fsec = file->f_security; | 3222 | struct file_security_struct *fsec = file->f_security; |
3208 | struct inode_security_struct *isec = inode->i_security; | 3223 | struct inode_security_struct *isec = inode_security(inode); |
3209 | u32 sid = current_sid(); | 3224 | u32 sid = current_sid(); |
3210 | 3225 | ||
3211 | if (!mask) | 3226 | if (!mask) |
@@ -3240,7 +3255,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, | |||
3240 | struct common_audit_data ad; | 3255 | struct common_audit_data ad; |
3241 | struct file_security_struct *fsec = file->f_security; | 3256 | struct file_security_struct *fsec = file->f_security; |
3242 | struct inode *inode = file_inode(file); | 3257 | struct inode *inode = file_inode(file); |
3243 | struct inode_security_struct *isec = inode->i_security; | 3258 | struct inode_security_struct *isec = inode_security(inode); |
3244 | struct lsm_ioctlop_audit ioctl; | 3259 | struct lsm_ioctlop_audit ioctl; |
3245 | u32 ssid = cred_sid(cred); | 3260 | u32 ssid = cred_sid(cred); |
3246 | int rc; | 3261 | int rc; |
@@ -3504,7 +3519,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred) | |||
3504 | struct inode_security_struct *isec; | 3519 | struct inode_security_struct *isec; |
3505 | 3520 | ||
3506 | fsec = file->f_security; | 3521 | fsec = file->f_security; |
3507 | isec = file_inode(file)->i_security; | 3522 | isec = inode_security(file_inode(file)); |
3508 | /* | 3523 | /* |
3509 | * Save inode label and policy sequence number | 3524 | * Save inode label and policy sequence number |
3510 | * at open-time so that selinux_file_permission | 3525 | * at open-time so that selinux_file_permission |
@@ -3622,7 +3637,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) | |||
3622 | */ | 3637 | */ |
3623 | static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | 3638 | static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) |
3624 | { | 3639 | { |
3625 | struct inode_security_struct *isec = inode->i_security; | 3640 | struct inode_security_struct *isec = inode_security(inode); |
3626 | struct task_security_struct *tsec = new->security; | 3641 | struct task_security_struct *tsec = new->security; |
3627 | u32 sid = current_sid(); | 3642 | u32 sid = current_sid(); |
3628 | int ret; | 3643 | int ret; |
@@ -4063,7 +4078,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
4063 | int type, int protocol, int kern) | 4078 | int type, int protocol, int kern) |
4064 | { | 4079 | { |
4065 | const struct task_security_struct *tsec = current_security(); | 4080 | const struct task_security_struct *tsec = current_security(); |
4066 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | 4081 | struct inode_security_struct *isec = inode_security(SOCK_INODE(sock)); |
4067 | struct sk_security_struct *sksec; | 4082 | struct sk_security_struct *sksec; |
4068 | int err = 0; | 4083 | int err = 0; |
4069 | 4084 | ||
@@ -4263,9 +4278,9 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
4263 | if (err) | 4278 | if (err) |
4264 | return err; | 4279 | return err; |
4265 | 4280 | ||
4266 | newisec = SOCK_INODE(newsock)->i_security; | 4281 | newisec = inode_security(SOCK_INODE(newsock)); |
4267 | 4282 | ||
4268 | isec = SOCK_INODE(sock)->i_security; | 4283 | isec = inode_security(SOCK_INODE(sock)); |
4269 | newisec->sclass = isec->sclass; | 4284 | newisec->sclass = isec->sclass; |
4270 | newisec->sid = isec->sid; | 4285 | newisec->sid = isec->sid; |
4271 | newisec->initialized = 1; | 4286 | newisec->initialized = 1; |
@@ -4603,7 +4618,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | |||
4603 | 4618 | ||
4604 | static void selinux_sock_graft(struct sock *sk, struct socket *parent) | 4619 | static void selinux_sock_graft(struct sock *sk, struct socket *parent) |
4605 | { | 4620 | { |
4606 | struct inode_security_struct *isec = SOCK_INODE(parent)->i_security; | 4621 | struct inode_security_struct *isec = inode_security(SOCK_INODE(parent)); |
4607 | struct sk_security_struct *sksec = sk->sk_security; | 4622 | struct sk_security_struct *sksec = sk->sk_security; |
4608 | 4623 | ||
4609 | if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || | 4624 | if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || |