aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c69
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);
691out: 691out:
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
988out_unlock:
989 mutex_unlock(&isec->lock);
990out: 990out:
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. */
1368static 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
1388static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) 1366static 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;