aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/inode.c9
-rw-r--r--security/selinux/Kconfig37
-rw-r--r--security/selinux/exports.c13
-rw-r--r--security/selinux/hooks.c69
-rw-r--r--security/selinux/include/objsec.h4
-rw-r--r--security/selinux/include/security.h7
-rw-r--r--security/selinux/selinuxfs.c1
-rw-r--r--security/selinux/ss/mls.c21
-rw-r--r--security/selinux/ss/policydb.c27
-rw-r--r--security/selinux/ss/policydb.h7
-rw-r--r--security/selinux/ss/services.c30
11 files changed, 133 insertions, 92 deletions
diff --git a/security/inode.c b/security/inode.c
index 47eb63480dac..49ee51529396 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -44,8 +44,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
44 44
45static int default_open(struct inode *inode, struct file *file) 45static int default_open(struct inode *inode, struct file *file)
46{ 46{
47 if (inode->u.generic_ip) 47 if (inode->i_private)
48 file->private_data = inode->u.generic_ip; 48 file->private_data = inode->i_private;
49 49
50 return 0; 50 return 0;
51} 51}
@@ -64,7 +64,6 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
64 inode->i_mode = mode; 64 inode->i_mode = mode;
65 inode->i_uid = 0; 65 inode->i_uid = 0;
66 inode->i_gid = 0; 66 inode->i_gid = 0;
67 inode->i_blksize = PAGE_CACHE_SIZE;
68 inode->i_blocks = 0; 67 inode->i_blocks = 0;
69 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 68 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
70 switch (mode & S_IFMT) { 69 switch (mode & S_IFMT) {
@@ -194,7 +193,7 @@ static int create_by_name(const char *name, mode_t mode,
194 * directory dentry if set. If this paramater is NULL, then the 193 * directory dentry if set. If this paramater is NULL, then the
195 * file will be created in the root of the securityfs filesystem. 194 * file will be created in the root of the securityfs filesystem.
196 * @data: a pointer to something that the caller will want to get to later 195 * @data: a pointer to something that the caller will want to get to later
197 * on. The inode.u.generic_ip pointer will point to this value on 196 * on. The inode.i_private pointer will point to this value on
198 * the open() call. 197 * the open() call.
199 * @fops: a pointer to a struct file_operations that should be used for 198 * @fops: a pointer to a struct file_operations that should be used for
200 * this file. 199 * this file.
@@ -240,7 +239,7 @@ struct dentry *securityfs_create_file(const char *name, mode_t mode,
240 if (fops) 239 if (fops)
241 dentry->d_inode->i_fop = fops; 240 dentry->d_inode->i_fop = fops;
242 if (data) 241 if (data)
243 dentry->d_inode->u.generic_ip = data; 242 dentry->d_inode->i_private = data;
244 } 243 }
245exit: 244exit:
246 return dentry; 245 return dentry;
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 814ddc42f1f4..293dbd6246c1 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -124,3 +124,40 @@ config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
124 124
125 If you are unsure what do do here, select N. 125 If you are unsure what do do here, select N.
126 126
127config SECURITY_SELINUX_POLICYDB_VERSION_MAX
128 bool "NSA SELinux maximum supported policy format version"
129 depends on SECURITY_SELINUX
130 default n
131 help
132 This option enables the maximum policy format version supported
133 by SELinux to be set to a particular value. This value is reported
134 to userspace via /selinux/policyvers and used at policy load time.
135 It can be adjusted downward to support legacy userland (init) that
136 does not correctly handle kernels that support newer policy versions.
137
138 Examples:
139 For the Fedora Core 3 or 4 Linux distributions, enable this option
140 and set the value via the next option. For Fedore Core 5 and later,
141 do not enable this option.
142
143 If you are unsure how to answer this question, answer N.
144
145config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
146 int "NSA SELinux maximum supported policy format version value"
147 depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
148 range 15 21
149 default 19
150 help
151 This option sets the value for the maximum policy format version
152 supported by SELinux.
153
154 Examples:
155 For Fedora Core 3, use 18.
156 For Fedora Core 4, use 19.
157
158 If you are unsure how to answer this question, look for the
159 policy format version supported by your policy toolchain, by
160 running 'checkpolicy -V'. Or look at what policy you have
161 installed under /etc/selinux/$SELINUXTYPE/policy, where
162 SELINUXTYPE is defined in your /etc/selinux/config.
163
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index 9d7737db5e51..b6f96943be1f 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -21,19 +21,10 @@
21#include "security.h" 21#include "security.h"
22#include "objsec.h" 22#include "objsec.h"
23 23
24void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid) 24int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
25{ 25{
26 struct task_security_struct *tsec = tsk->security;
27 if (selinux_enabled) 26 if (selinux_enabled)
28 *ctxid = tsec->sid; 27 return security_sid_to_context(sid, ctx, ctxlen);
29 else
30 *ctxid = 0;
31}
32
33int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen)
34{
35 if (selinux_enabled)
36 return security_sid_to_context(ctxid, ctx, ctxlen);
37 else { 28 else {
38 *ctx = NULL; 29 *ctx = NULL;
39 *ctxlen = 0; 30 *ctxlen = 0;
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;
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 0a39bfd1319f..ef2267fea8bd 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -44,7 +44,7 @@ struct inode_security_struct {
44 u32 sid; /* SID of this object */ 44 u32 sid; /* SID of this object */
45 u16 sclass; /* security class of this object */ 45 u16 sclass; /* security class of this object */
46 unsigned char initialized; /* initialization flag */ 46 unsigned char initialized; /* initialization flag */
47 struct semaphore sem; 47 struct mutex lock;
48 unsigned char inherit; /* inherit SID from parent entry */ 48 unsigned char inherit; /* inherit SID from parent entry */
49}; 49};
50 50
@@ -63,7 +63,7 @@ struct superblock_security_struct {
63 unsigned int behavior; /* labeling behavior */ 63 unsigned int behavior; /* labeling behavior */
64 unsigned char initialized; /* initialization flag */ 64 unsigned char initialized; /* initialization flag */
65 unsigned char proc; /* proc fs */ 65 unsigned char proc; /* proc fs */
66 struct semaphore sem; 66 struct mutex lock;
67 struct list_head isec_head; 67 struct list_head isec_head;
68 spinlock_t isec_lock; 68 spinlock_t isec_lock;
69}; 69};
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 911954a692fa..1ef79172cc8c 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -24,10 +24,15 @@
24#define POLICYDB_VERSION_VALIDATETRANS 19 24#define POLICYDB_VERSION_VALIDATETRANS 19
25#define POLICYDB_VERSION_MLS 19 25#define POLICYDB_VERSION_MLS 19
26#define POLICYDB_VERSION_AVTAB 20 26#define POLICYDB_VERSION_AVTAB 20
27#define POLICYDB_VERSION_RANGETRANS 21
27 28
28/* Range of policy versions we understand*/ 29/* Range of policy versions we understand*/
29#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 30#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
30#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB 31#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
32#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
33#else
34#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS
35#endif
31 36
32extern int selinux_enabled; 37extern int selinux_enabled;
33extern int selinux_mls_enabled; 38extern int selinux_mls_enabled;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 00534c302ba2..bab7b386cb8d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -771,7 +771,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode)
771 if (ret) { 771 if (ret) {
772 ret->i_mode = mode; 772 ret->i_mode = mode;
773 ret->i_uid = ret->i_gid = 0; 773 ret->i_uid = ret->i_gid = 0;
774 ret->i_blksize = PAGE_CACHE_SIZE;
775 ret->i_blocks = 0; 774 ret->i_blocks = 0;
776 ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; 775 ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
777 } 776 }
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 119bd6078ba1..c713af23250a 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -530,22 +530,21 @@ int mls_compute_sid(struct context *scontext,
530 u32 specified, 530 u32 specified,
531 struct context *newcontext) 531 struct context *newcontext)
532{ 532{
533 struct range_trans *rtr;
534
533 if (!selinux_mls_enabled) 535 if (!selinux_mls_enabled)
534 return 0; 536 return 0;
535 537
536 switch (specified) { 538 switch (specified) {
537 case AVTAB_TRANSITION: 539 case AVTAB_TRANSITION:
538 if (tclass == SECCLASS_PROCESS) { 540 /* Look for a range transition rule. */
539 struct range_trans *rangetr; 541 for (rtr = policydb.range_tr; rtr; rtr = rtr->next) {
540 /* Look for a range transition rule. */ 542 if (rtr->source_type == scontext->type &&
541 for (rangetr = policydb.range_tr; rangetr; 543 rtr->target_type == tcontext->type &&
542 rangetr = rangetr->next) { 544 rtr->target_class == tclass) {
543 if (rangetr->dom == scontext->type && 545 /* Set the range from the rule */
544 rangetr->type == tcontext->type) { 546 return mls_range_set(newcontext,
545 /* Set the range from the rule */ 547 &rtr->target_range);
546 return mls_range_set(newcontext,
547 &rangetr->range);
548 }
549 } 548 }
550 } 549 }
551 /* Fallthrough */ 550 /* Fallthrough */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index f03960e697ce..b18895302555 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -96,6 +96,11 @@ static struct policydb_compat_info policydb_compat[] = {
96 .sym_num = SYM_NUM, 96 .sym_num = SYM_NUM,
97 .ocon_num = OCON_NUM, 97 .ocon_num = OCON_NUM,
98 }, 98 },
99 {
100 .version = POLICYDB_VERSION_RANGETRANS,
101 .sym_num = SYM_NUM,
102 .ocon_num = OCON_NUM,
103 },
99}; 104};
100 105
101static struct policydb_compat_info *policydb_lookup_compat(int version) 106static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -645,15 +650,15 @@ void policydb_destroy(struct policydb *p)
645 650
646 for (rt = p->range_tr; rt; rt = rt -> next) { 651 for (rt = p->range_tr; rt; rt = rt -> next) {
647 if (lrt) { 652 if (lrt) {
648 ebitmap_destroy(&lrt->range.level[0].cat); 653 ebitmap_destroy(&lrt->target_range.level[0].cat);
649 ebitmap_destroy(&lrt->range.level[1].cat); 654 ebitmap_destroy(&lrt->target_range.level[1].cat);
650 kfree(lrt); 655 kfree(lrt);
651 } 656 }
652 lrt = rt; 657 lrt = rt;
653 } 658 }
654 if (lrt) { 659 if (lrt) {
655 ebitmap_destroy(&lrt->range.level[0].cat); 660 ebitmap_destroy(&lrt->target_range.level[0].cat);
656 ebitmap_destroy(&lrt->range.level[1].cat); 661 ebitmap_destroy(&lrt->target_range.level[1].cat);
657 kfree(lrt); 662 kfree(lrt);
658 } 663 }
659 664
@@ -1829,6 +1834,7 @@ int policydb_read(struct policydb *p, void *fp)
1829 } 1834 }
1830 1835
1831 if (p->policyvers >= POLICYDB_VERSION_MLS) { 1836 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1837 int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS;
1832 rc = next_entry(buf, fp, sizeof(u32)); 1838 rc = next_entry(buf, fp, sizeof(u32));
1833 if (rc < 0) 1839 if (rc < 0)
1834 goto bad; 1840 goto bad;
@@ -1847,9 +1853,16 @@ int policydb_read(struct policydb *p, void *fp)
1847 rc = next_entry(buf, fp, (sizeof(u32) * 2)); 1853 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1848 if (rc < 0) 1854 if (rc < 0)
1849 goto bad; 1855 goto bad;
1850 rt->dom = le32_to_cpu(buf[0]); 1856 rt->source_type = le32_to_cpu(buf[0]);
1851 rt->type = le32_to_cpu(buf[1]); 1857 rt->target_type = le32_to_cpu(buf[1]);
1852 rc = mls_read_range_helper(&rt->range, fp); 1858 if (new_rangetr) {
1859 rc = next_entry(buf, fp, sizeof(u32));
1860 if (rc < 0)
1861 goto bad;
1862 rt->target_class = le32_to_cpu(buf[0]);
1863 } else
1864 rt->target_class = SECCLASS_PROCESS;
1865 rc = mls_read_range_helper(&rt->target_range, fp);
1853 if (rc) 1866 if (rc)
1854 goto bad; 1867 goto bad;
1855 lrt = rt; 1868 lrt = rt;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index b1340711f721..8319d5ff5944 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -106,9 +106,10 @@ struct cat_datum {
106}; 106};
107 107
108struct range_trans { 108struct range_trans {
109 u32 dom; /* current process domain */ 109 u32 source_type;
110 u32 type; /* program executable type */ 110 u32 target_type;
111 struct mls_range range; /* new range */ 111 u32 target_class;
112 struct mls_range target_range;
112 struct range_trans *next; 113 struct range_trans *next;
113}; 114};
114 115
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 7eb69a602d8f..0c219a1b3243 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2003,7 +2003,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
2003 return rc; 2003 return rc;
2004} 2004}
2005 2005
2006int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, 2006int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
2007 struct selinux_audit_rule *rule, 2007 struct selinux_audit_rule *rule,
2008 struct audit_context *actx) 2008 struct audit_context *actx)
2009{ 2009{
@@ -2026,11 +2026,11 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
2026 goto out; 2026 goto out;
2027 } 2027 }
2028 2028
2029 ctxt = sidtab_search(&sidtab, ctxid); 2029 ctxt = sidtab_search(&sidtab, sid);
2030 if (!ctxt) { 2030 if (!ctxt) {
2031 audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, 2031 audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
2032 "selinux_audit_rule_match: unrecognized SID %d\n", 2032 "selinux_audit_rule_match: unrecognized SID %d\n",
2033 ctxid); 2033 sid);
2034 match = -ENOENT; 2034 match = -ENOENT;
2035 goto out; 2035 goto out;
2036 } 2036 }
@@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2502{ 2502{
2503 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; 2503 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2504 struct sk_security_struct *sksec = sk->sk_security; 2504 struct sk_security_struct *sksec = sk->sk_security;
2505 struct netlbl_lsm_secattr secattr;
2506 u32 nlbl_peer_sid;
2505 2507
2506 sksec->sclass = isec->sclass; 2508 sksec->sclass = isec->sclass;
2507 2509
2508 if (sk->sk_family != PF_INET) 2510 if (sk->sk_family != PF_INET)
2509 return; 2511 return;
2510 2512
2513 netlbl_secattr_init(&secattr);
2514 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
2515 selinux_netlbl_secattr_to_sid(NULL,
2516 &secattr,
2517 sksec->sid,
2518 &nlbl_peer_sid) == 0)
2519 sksec->peer_sid = nlbl_peer_sid;
2520 netlbl_secattr_destroy(&secattr, 0);
2521
2511 sksec->nlbl_state = NLBL_REQUIRE; 2522 sksec->nlbl_state = NLBL_REQUIRE;
2512 sksec->peer_sid = sksec->sid;
2513 2523
2514 /* Try to set the NetLabel on the socket to save time later, if we fail 2524 /* Try to set the NetLabel on the socket to save time later, if we fail
2515 * here we will pick up the pieces in later calls to 2525 * here we will pick up the pieces in later calls to
@@ -2568,7 +2578,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2568 sock = SOCKET_I(inode); 2578 sock = SOCKET_I(inode);
2569 isec = inode->i_security; 2579 isec = inode->i_security;
2570 sksec = sock->sk->sk_security; 2580 sksec = sock->sk->sk_security;
2571 down(&isec->sem); 2581 mutex_lock(&isec->lock);
2572 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && 2582 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE &&
2573 (mask & (MAY_WRITE | MAY_APPEND)))) { 2583 (mask & (MAY_WRITE | MAY_APPEND)))) {
2574 lock_sock(sock->sk); 2584 lock_sock(sock->sk);
@@ -2576,7 +2586,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2576 release_sock(sock->sk); 2586 release_sock(sock->sk);
2577 } else 2587 } else
2578 rc = 0; 2588 rc = 0;
2579 up(&isec->sem); 2589 mutex_unlock(&isec->lock);
2580 2590
2581 return rc; 2591 return rc;
2582} 2592}
@@ -2601,7 +2611,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2601 u32 netlbl_sid; 2611 u32 netlbl_sid;
2602 u32 recv_perm; 2612 u32 recv_perm;
2603 2613
2604 rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid); 2614 rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid);
2605 if (rc != 0) 2615 if (rc != 0)
2606 return rc; 2616 return rc;
2607 2617
@@ -2610,13 +2620,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2610 2620
2611 switch (sksec->sclass) { 2621 switch (sksec->sclass) {
2612 case SECCLASS_UDP_SOCKET: 2622 case SECCLASS_UDP_SOCKET:
2613 recv_perm = UDP_SOCKET__RECV_MSG; 2623 recv_perm = UDP_SOCKET__RECVFROM;
2614 break; 2624 break;
2615 case SECCLASS_TCP_SOCKET: 2625 case SECCLASS_TCP_SOCKET:
2616 recv_perm = TCP_SOCKET__RECV_MSG; 2626 recv_perm = TCP_SOCKET__RECVFROM;
2617 break; 2627 break;
2618 default: 2628 default:
2619 recv_perm = RAWIP_SOCKET__RECV_MSG; 2629 recv_perm = RAWIP_SOCKET__RECVFROM;
2620 } 2630 }
2621 2631
2622 rc = avc_has_perm(sksec->sid, 2632 rc = avc_has_perm(sksec->sid,