diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 69 |
1 files changed, 28 insertions, 41 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5a66c4c09f7a..e4d81a42fca4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <net/ip.h> /* for sysctl_local_port_range[] */ | 51 | #include <net/ip.h> /* for sysctl_local_port_range[] */ |
52 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ | 52 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ |
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | #include <asm/semaphore.h> | ||
55 | #include <asm/ioctls.h> | 54 | #include <asm/ioctls.h> |
56 | #include <linux/bitops.h> | 55 | #include <linux/bitops.h> |
57 | #include <linux/interrupt.h> | 56 | #include <linux/interrupt.h> |
@@ -71,6 +70,7 @@ | |||
71 | #include <linux/audit.h> | 70 | #include <linux/audit.h> |
72 | #include <linux/string.h> | 71 | #include <linux/string.h> |
73 | #include <linux/selinux.h> | 72 | #include <linux/selinux.h> |
73 | #include <linux/mutex.h> | ||
74 | 74 | ||
75 | #include "avc.h" | 75 | #include "avc.h" |
76 | #include "objsec.h" | 76 | #include "objsec.h" |
@@ -185,7 +185,7 @@ static int inode_alloc_security(struct inode *inode) | |||
185 | return -ENOMEM; | 185 | return -ENOMEM; |
186 | 186 | ||
187 | memset(isec, 0, sizeof(*isec)); | 187 | memset(isec, 0, sizeof(*isec)); |
188 | init_MUTEX(&isec->sem); | 188 | mutex_init(&isec->lock); |
189 | INIT_LIST_HEAD(&isec->list); | 189 | INIT_LIST_HEAD(&isec->list); |
190 | isec->inode = inode; | 190 | isec->inode = inode; |
191 | isec->sid = SECINITSID_UNLABELED; | 191 | isec->sid = SECINITSID_UNLABELED; |
@@ -242,7 +242,7 @@ static int superblock_alloc_security(struct super_block *sb) | |||
242 | if (!sbsec) | 242 | if (!sbsec) |
243 | return -ENOMEM; | 243 | return -ENOMEM; |
244 | 244 | ||
245 | init_MUTEX(&sbsec->sem); | 245 | mutex_init(&sbsec->lock); |
246 | INIT_LIST_HEAD(&sbsec->list); | 246 | INIT_LIST_HEAD(&sbsec->list); |
247 | INIT_LIST_HEAD(&sbsec->isec_head); | 247 | INIT_LIST_HEAD(&sbsec->isec_head); |
248 | spin_lock_init(&sbsec->isec_lock); | 248 | spin_lock_init(&sbsec->isec_lock); |
@@ -594,7 +594,7 @@ static int superblock_doinit(struct super_block *sb, void *data) | |||
594 | struct inode *inode = root->d_inode; | 594 | struct inode *inode = root->d_inode; |
595 | int rc = 0; | 595 | int rc = 0; |
596 | 596 | ||
597 | down(&sbsec->sem); | 597 | mutex_lock(&sbsec->lock); |
598 | if (sbsec->initialized) | 598 | if (sbsec->initialized) |
599 | goto out; | 599 | goto out; |
600 | 600 | ||
@@ -689,7 +689,7 @@ next_inode: | |||
689 | } | 689 | } |
690 | spin_unlock(&sbsec->isec_lock); | 690 | spin_unlock(&sbsec->isec_lock); |
691 | out: | 691 | out: |
692 | up(&sbsec->sem); | 692 | mutex_unlock(&sbsec->lock); |
693 | return rc; | 693 | return rc; |
694 | } | 694 | } |
695 | 695 | ||
@@ -843,15 +843,13 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
843 | char *context = NULL; | 843 | char *context = NULL; |
844 | unsigned len = 0; | 844 | unsigned len = 0; |
845 | int rc = 0; | 845 | int rc = 0; |
846 | int hold_sem = 0; | ||
847 | 846 | ||
848 | if (isec->initialized) | 847 | if (isec->initialized) |
849 | goto out; | 848 | goto out; |
850 | 849 | ||
851 | down(&isec->sem); | 850 | mutex_lock(&isec->lock); |
852 | hold_sem = 1; | ||
853 | if (isec->initialized) | 851 | if (isec->initialized) |
854 | goto out; | 852 | goto out_unlock; |
855 | 853 | ||
856 | sbsec = inode->i_sb->s_security; | 854 | sbsec = inode->i_sb->s_security; |
857 | if (!sbsec->initialized) { | 855 | if (!sbsec->initialized) { |
@@ -862,7 +860,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
862 | if (list_empty(&isec->list)) | 860 | if (list_empty(&isec->list)) |
863 | list_add(&isec->list, &sbsec->isec_head); | 861 | list_add(&isec->list, &sbsec->isec_head); |
864 | spin_unlock(&sbsec->isec_lock); | 862 | spin_unlock(&sbsec->isec_lock); |
865 | goto out; | 863 | goto out_unlock; |
866 | } | 864 | } |
867 | 865 | ||
868 | switch (sbsec->behavior) { | 866 | switch (sbsec->behavior) { |
@@ -885,7 +883,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
885 | printk(KERN_WARNING "%s: no dentry for dev=%s " | 883 | printk(KERN_WARNING "%s: no dentry for dev=%s " |
886 | "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id, | 884 | "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id, |
887 | inode->i_ino); | 885 | inode->i_ino); |
888 | goto out; | 886 | goto out_unlock; |
889 | } | 887 | } |
890 | 888 | ||
891 | len = INITCONTEXTLEN; | 889 | len = INITCONTEXTLEN; |
@@ -893,7 +891,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
893 | if (!context) { | 891 | if (!context) { |
894 | rc = -ENOMEM; | 892 | rc = -ENOMEM; |
895 | dput(dentry); | 893 | dput(dentry); |
896 | goto out; | 894 | goto out_unlock; |
897 | } | 895 | } |
898 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, | 896 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, |
899 | context, len); | 897 | context, len); |
@@ -903,7 +901,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
903 | NULL, 0); | 901 | NULL, 0); |
904 | if (rc < 0) { | 902 | if (rc < 0) { |
905 | dput(dentry); | 903 | dput(dentry); |
906 | goto out; | 904 | goto out_unlock; |
907 | } | 905 | } |
908 | kfree(context); | 906 | kfree(context); |
909 | len = rc; | 907 | len = rc; |
@@ -911,7 +909,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
911 | if (!context) { | 909 | if (!context) { |
912 | rc = -ENOMEM; | 910 | rc = -ENOMEM; |
913 | dput(dentry); | 911 | dput(dentry); |
914 | goto out; | 912 | goto out_unlock; |
915 | } | 913 | } |
916 | rc = inode->i_op->getxattr(dentry, | 914 | rc = inode->i_op->getxattr(dentry, |
917 | XATTR_NAME_SELINUX, | 915 | XATTR_NAME_SELINUX, |
@@ -924,7 +922,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
924 | "%d for dev=%s ino=%ld\n", __FUNCTION__, | 922 | "%d for dev=%s ino=%ld\n", __FUNCTION__, |
925 | -rc, inode->i_sb->s_id, inode->i_ino); | 923 | -rc, inode->i_sb->s_id, inode->i_ino); |
926 | kfree(context); | 924 | kfree(context); |
927 | goto out; | 925 | goto out_unlock; |
928 | } | 926 | } |
929 | /* Map ENODATA to the default file SID */ | 927 | /* Map ENODATA to the default file SID */ |
930 | sid = sbsec->def_sid; | 928 | sid = sbsec->def_sid; |
@@ -960,7 +958,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
960 | isec->sclass, | 958 | isec->sclass, |
961 | &sid); | 959 | &sid); |
962 | if (rc) | 960 | if (rc) |
963 | goto out; | 961 | goto out_unlock; |
964 | isec->sid = sid; | 962 | isec->sid = sid; |
965 | break; | 963 | break; |
966 | case SECURITY_FS_USE_MNTPOINT: | 964 | case SECURITY_FS_USE_MNTPOINT: |
@@ -978,7 +976,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
978 | isec->sclass, | 976 | isec->sclass, |
979 | &sid); | 977 | &sid); |
980 | if (rc) | 978 | if (rc) |
981 | goto out; | 979 | goto out_unlock; |
982 | isec->sid = sid; | 980 | isec->sid = sid; |
983 | } | 981 | } |
984 | } | 982 | } |
@@ -987,12 +985,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
987 | 985 | ||
988 | isec->initialized = 1; | 986 | isec->initialized = 1; |
989 | 987 | ||
988 | out_unlock: | ||
989 | mutex_unlock(&isec->lock); | ||
990 | out: | 990 | out: |
991 | if (isec->sclass == SECCLASS_FILE) | 991 | if (isec->sclass == SECCLASS_FILE) |
992 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 992 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
993 | |||
994 | if (hold_sem) | ||
995 | up(&isec->sem); | ||
996 | return rc; | 993 | return rc; |
997 | } | 994 | } |
998 | 995 | ||
@@ -1364,25 +1361,6 @@ static inline u32 file_to_av(struct file *file) | |||
1364 | return av; | 1361 | return av; |
1365 | } | 1362 | } |
1366 | 1363 | ||
1367 | /* Set an inode's SID to a specified value. */ | ||
1368 | static int inode_security_set_sid(struct inode *inode, u32 sid) | ||
1369 | { | ||
1370 | struct inode_security_struct *isec = inode->i_security; | ||
1371 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; | ||
1372 | |||
1373 | if (!sbsec->initialized) { | ||
1374 | /* Defer initialization to selinux_complete_init. */ | ||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1378 | down(&isec->sem); | ||
1379 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
1380 | isec->sid = sid; | ||
1381 | isec->initialized = 1; | ||
1382 | up(&isec->sem); | ||
1383 | return 0; | ||
1384 | } | ||
1385 | |||
1386 | /* Hook functions begin here. */ | 1364 | /* Hook functions begin here. */ |
1387 | 1365 | ||
1388 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) | 1366 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) |
@@ -1711,10 +1689,12 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1711 | { | 1689 | { |
1712 | struct avc_audit_data ad; | 1690 | struct avc_audit_data ad; |
1713 | struct file *file, *devnull = NULL; | 1691 | struct file *file, *devnull = NULL; |
1714 | struct tty_struct *tty = current->signal->tty; | 1692 | struct tty_struct *tty; |
1715 | struct fdtable *fdt; | 1693 | struct fdtable *fdt; |
1716 | long j = -1; | 1694 | long j = -1; |
1717 | 1695 | ||
1696 | mutex_lock(&tty_mutex); | ||
1697 | tty = current->signal->tty; | ||
1718 | if (tty) { | 1698 | if (tty) { |
1719 | file_list_lock(); | 1699 | file_list_lock(); |
1720 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); | 1700 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); |
@@ -1734,6 +1714,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1734 | } | 1714 | } |
1735 | file_list_unlock(); | 1715 | file_list_unlock(); |
1736 | } | 1716 | } |
1717 | mutex_unlock(&tty_mutex); | ||
1737 | 1718 | ||
1738 | /* Revalidate access to inherited open files. */ | 1719 | /* Revalidate access to inherited open files. */ |
1739 | 1720 | ||
@@ -2091,7 +2072,13 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2091 | } | 2072 | } |
2092 | } | 2073 | } |
2093 | 2074 | ||
2094 | inode_security_set_sid(inode, newsid); | 2075 | /* Possibly defer initialization to selinux_complete_init. */ |
2076 | if (sbsec->initialized) { | ||
2077 | struct inode_security_struct *isec = inode->i_security; | ||
2078 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2079 | isec->sid = newsid; | ||
2080 | isec->initialized = 1; | ||
2081 | } | ||
2095 | 2082 | ||
2096 | if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) | 2083 | if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) |
2097 | return -EOPNOTSUPP; | 2084 | return -EOPNOTSUPP; |