diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/inode.c | 9 | ||||
-rw-r--r-- | security/selinux/Kconfig | 37 | ||||
-rw-r--r-- | security/selinux/exports.c | 13 | ||||
-rw-r--r-- | security/selinux/hooks.c | 69 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 4 | ||||
-rw-r--r-- | security/selinux/include/security.h | 7 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 1 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 21 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 27 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 7 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 30 |
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 | ||
45 | static int default_open(struct inode *inode, struct file *file) | 45 | static 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 | } |
245 | exit: | 244 | exit: |
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 | ||
127 | config 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 | |||
145 | config 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 | ||
24 | void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid) | 24 | int 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 | |||
33 | int 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); |
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; |
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 | ||
32 | extern int selinux_enabled; | 37 | extern int selinux_enabled; |
33 | extern int selinux_mls_enabled; | 38 | extern 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 | ||
101 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 106 | static 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 | ||
108 | struct range_trans { | 108 | struct 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 | ||
2006 | int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | 2006 | int 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, |