diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/process_keys.c | 7 | ||||
-rw-r--r-- | security/selinux/hooks.c | 14 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 112 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 9 |
4 files changed, 68 insertions, 74 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 74cb79eb917e..f6940618e345 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -16,11 +16,12 @@ | |||
16 | #include <linux/keyctl.h> | 16 | #include <linux/keyctl.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/mutex.h> | ||
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include "internal.h" | 21 | #include "internal.h" |
21 | 22 | ||
22 | /* session keyring create vs join semaphore */ | 23 | /* session keyring create vs join semaphore */ |
23 | static DECLARE_MUTEX(key_session_sem); | 24 | static DEFINE_MUTEX(key_session_mutex); |
24 | 25 | ||
25 | /* the root user's tracking struct */ | 26 | /* the root user's tracking struct */ |
26 | struct key_user root_key_user = { | 27 | struct key_user root_key_user = { |
@@ -711,7 +712,7 @@ long join_session_keyring(const char *name) | |||
711 | } | 712 | } |
712 | 713 | ||
713 | /* allow the user to join or create a named keyring */ | 714 | /* allow the user to join or create a named keyring */ |
714 | down(&key_session_sem); | 715 | mutex_lock(&key_session_mutex); |
715 | 716 | ||
716 | /* look for an existing keyring of this name */ | 717 | /* look for an existing keyring of this name */ |
717 | keyring = find_keyring_by_name(name, 0); | 718 | keyring = find_keyring_by_name(name, 0); |
@@ -737,7 +738,7 @@ long join_session_keyring(const char *name) | |||
737 | key_put(keyring); | 738 | key_put(keyring); |
738 | 739 | ||
739 | error2: | 740 | error2: |
740 | up(&key_session_sem); | 741 | mutex_unlock(&key_session_mutex); |
741 | error: | 742 | error: |
742 | return ret; | 743 | return ret; |
743 | 744 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5b16196f2823..ccaf988f3729 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -117,6 +117,8 @@ static struct security_operations *secondary_ops = NULL; | |||
117 | static LIST_HEAD(superblock_security_head); | 117 | static LIST_HEAD(superblock_security_head); |
118 | static DEFINE_SPINLOCK(sb_security_lock); | 118 | static DEFINE_SPINLOCK(sb_security_lock); |
119 | 119 | ||
120 | static kmem_cache_t *sel_inode_cache; | ||
121 | |||
120 | /* Allocate and free functions for each kind of security blob. */ | 122 | /* Allocate and free functions for each kind of security blob. */ |
121 | 123 | ||
122 | static int task_alloc_security(struct task_struct *task) | 124 | static int task_alloc_security(struct task_struct *task) |
@@ -146,10 +148,11 @@ static int inode_alloc_security(struct inode *inode) | |||
146 | struct task_security_struct *tsec = current->security; | 148 | struct task_security_struct *tsec = current->security; |
147 | struct inode_security_struct *isec; | 149 | struct inode_security_struct *isec; |
148 | 150 | ||
149 | isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL); | 151 | isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL); |
150 | if (!isec) | 152 | if (!isec) |
151 | return -ENOMEM; | 153 | return -ENOMEM; |
152 | 154 | ||
155 | memset(isec, 0, sizeof(*isec)); | ||
153 | init_MUTEX(&isec->sem); | 156 | init_MUTEX(&isec->sem); |
154 | INIT_LIST_HEAD(&isec->list); | 157 | INIT_LIST_HEAD(&isec->list); |
155 | isec->inode = inode; | 158 | isec->inode = inode; |
@@ -172,7 +175,7 @@ static void inode_free_security(struct inode *inode) | |||
172 | spin_unlock(&sbsec->isec_lock); | 175 | spin_unlock(&sbsec->isec_lock); |
173 | 176 | ||
174 | inode->i_security = NULL; | 177 | inode->i_security = NULL; |
175 | kfree(isec); | 178 | kmem_cache_free(sel_inode_cache, isec); |
176 | } | 179 | } |
177 | 180 | ||
178 | static int file_alloc_security(struct file *file) | 181 | static int file_alloc_security(struct file *file) |
@@ -1929,7 +1932,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
1929 | struct task_security_struct *tsec; | 1932 | struct task_security_struct *tsec; |
1930 | struct inode_security_struct *dsec; | 1933 | struct inode_security_struct *dsec; |
1931 | struct superblock_security_struct *sbsec; | 1934 | struct superblock_security_struct *sbsec; |
1932 | struct inode_security_struct *isec; | ||
1933 | u32 newsid, clen; | 1935 | u32 newsid, clen; |
1934 | int rc; | 1936 | int rc; |
1935 | char *namep = NULL, *context; | 1937 | char *namep = NULL, *context; |
@@ -1937,7 +1939,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
1937 | tsec = current->security; | 1939 | tsec = current->security; |
1938 | dsec = dir->i_security; | 1940 | dsec = dir->i_security; |
1939 | sbsec = dir->i_sb->s_security; | 1941 | sbsec = dir->i_sb->s_security; |
1940 | isec = inode->i_security; | ||
1941 | 1942 | ||
1942 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | 1943 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { |
1943 | newsid = tsec->create_sid; | 1944 | newsid = tsec->create_sid; |
@@ -1957,7 +1958,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
1957 | 1958 | ||
1958 | inode_security_set_sid(inode, newsid); | 1959 | inode_security_set_sid(inode, newsid); |
1959 | 1960 | ||
1960 | if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) | 1961 | if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) |
1961 | return -EOPNOTSUPP; | 1962 | return -EOPNOTSUPP; |
1962 | 1963 | ||
1963 | if (name) { | 1964 | if (name) { |
@@ -4408,6 +4409,9 @@ static __init int selinux_init(void) | |||
4408 | tsec = current->security; | 4409 | tsec = current->security; |
4409 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | 4410 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
4410 | 4411 | ||
4412 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | ||
4413 | sizeof(struct inode_security_struct), | ||
4414 | 0, SLAB_PANIC, NULL, NULL); | ||
4411 | avc_init(); | 4415 | avc_init(); |
4412 | 4416 | ||
4413 | original_ops = secondary_ops = security_ops; | 4417 | original_ops = secondary_ops = security_ops; |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index b5fa02d17b1e..f5d78365488f 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/vmalloc.h> | 16 | #include <linux/vmalloc.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/mutex.h> | ||
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/string.h> | 20 | #include <linux/string.h> |
20 | #include <linux/security.h> | 21 | #include <linux/security.h> |
@@ -44,7 +45,7 @@ static int __init checkreqprot_setup(char *str) | |||
44 | __setup("checkreqprot=", checkreqprot_setup); | 45 | __setup("checkreqprot=", checkreqprot_setup); |
45 | 46 | ||
46 | 47 | ||
47 | static DECLARE_MUTEX(sel_sem); | 48 | static DEFINE_MUTEX(sel_mutex); |
48 | 49 | ||
49 | /* global data for booleans */ | 50 | /* global data for booleans */ |
50 | static struct dentry *bool_dir = NULL; | 51 | static struct dentry *bool_dir = NULL; |
@@ -230,7 +231,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf, | |||
230 | ssize_t length; | 231 | ssize_t length; |
231 | void *data = NULL; | 232 | void *data = NULL; |
232 | 233 | ||
233 | down(&sel_sem); | 234 | mutex_lock(&sel_mutex); |
234 | 235 | ||
235 | length = task_has_security(current, SECURITY__LOAD_POLICY); | 236 | length = task_has_security(current, SECURITY__LOAD_POLICY); |
236 | if (length) | 237 | if (length) |
@@ -262,7 +263,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf, | |||
262 | else | 263 | else |
263 | length = count; | 264 | length = count; |
264 | out: | 265 | out: |
265 | up(&sel_sem); | 266 | mutex_unlock(&sel_mutex); |
266 | vfree(data); | 267 | vfree(data); |
267 | return length; | 268 | return length; |
268 | } | 269 | } |
@@ -709,12 +710,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
709 | { | 710 | { |
710 | char *page = NULL; | 711 | char *page = NULL; |
711 | ssize_t length; | 712 | ssize_t length; |
712 | ssize_t end; | ||
713 | ssize_t ret; | 713 | ssize_t ret; |
714 | int cur_enforcing; | 714 | int cur_enforcing; |
715 | struct inode *inode; | 715 | struct inode *inode; |
716 | 716 | ||
717 | down(&sel_sem); | 717 | mutex_lock(&sel_mutex); |
718 | 718 | ||
719 | ret = -EFAULT; | 719 | ret = -EFAULT; |
720 | 720 | ||
@@ -740,26 +740,9 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
740 | 740 | ||
741 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, | 741 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, |
742 | bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); | 742 | bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); |
743 | if (length < 0) { | 743 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
744 | ret = length; | ||
745 | goto out; | ||
746 | } | ||
747 | |||
748 | if (*ppos >= length) { | ||
749 | ret = 0; | ||
750 | goto out; | ||
751 | } | ||
752 | if (count + *ppos > length) | ||
753 | count = length - *ppos; | ||
754 | end = count + *ppos; | ||
755 | if (copy_to_user(buf, (char *) page + *ppos, count)) { | ||
756 | ret = -EFAULT; | ||
757 | goto out; | ||
758 | } | ||
759 | *ppos = end; | ||
760 | ret = count; | ||
761 | out: | 744 | out: |
762 | up(&sel_sem); | 745 | mutex_unlock(&sel_mutex); |
763 | if (page) | 746 | if (page) |
764 | free_page((unsigned long)page); | 747 | free_page((unsigned long)page); |
765 | return ret; | 748 | return ret; |
@@ -773,7 +756,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
773 | int new_value; | 756 | int new_value; |
774 | struct inode *inode; | 757 | struct inode *inode; |
775 | 758 | ||
776 | down(&sel_sem); | 759 | mutex_lock(&sel_mutex); |
777 | 760 | ||
778 | length = task_has_security(current, SECURITY__SETBOOL); | 761 | length = task_has_security(current, SECURITY__SETBOOL); |
779 | if (length) | 762 | if (length) |
@@ -812,7 +795,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
812 | length = count; | 795 | length = count; |
813 | 796 | ||
814 | out: | 797 | out: |
815 | up(&sel_sem); | 798 | mutex_unlock(&sel_mutex); |
816 | if (page) | 799 | if (page) |
817 | free_page((unsigned long) page); | 800 | free_page((unsigned long) page); |
818 | return length; | 801 | return length; |
@@ -831,7 +814,7 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
831 | ssize_t length = -EFAULT; | 814 | ssize_t length = -EFAULT; |
832 | int new_value; | 815 | int new_value; |
833 | 816 | ||
834 | down(&sel_sem); | 817 | mutex_lock(&sel_mutex); |
835 | 818 | ||
836 | length = task_has_security(current, SECURITY__SETBOOL); | 819 | length = task_has_security(current, SECURITY__SETBOOL); |
837 | if (length) | 820 | if (length) |
@@ -869,7 +852,7 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
869 | length = count; | 852 | length = count; |
870 | 853 | ||
871 | out: | 854 | out: |
872 | up(&sel_sem); | 855 | mutex_unlock(&sel_mutex); |
873 | if (page) | 856 | if (page) |
874 | free_page((unsigned long) page); | 857 | free_page((unsigned long) page); |
875 | return length; | 858 | return length; |
@@ -987,7 +970,7 @@ out: | |||
987 | return ret; | 970 | return ret; |
988 | err: | 971 | err: |
989 | kfree(values); | 972 | kfree(values); |
990 | d_genocide(dir); | 973 | sel_remove_bools(dir); |
991 | ret = -ENOMEM; | 974 | ret = -ENOMEM; |
992 | goto out; | 975 | goto out; |
993 | } | 976 | } |
@@ -1168,37 +1151,38 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1168 | dentry = d_alloc_name(dir, files[i].name); | 1151 | dentry = d_alloc_name(dir, files[i].name); |
1169 | if (!dentry) { | 1152 | if (!dentry) { |
1170 | ret = -ENOMEM; | 1153 | ret = -ENOMEM; |
1171 | goto err; | 1154 | goto out; |
1172 | } | 1155 | } |
1173 | 1156 | ||
1174 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); | 1157 | inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); |
1175 | if (!inode) { | 1158 | if (!inode) { |
1176 | ret = -ENOMEM; | 1159 | ret = -ENOMEM; |
1177 | goto err; | 1160 | goto out; |
1178 | } | 1161 | } |
1179 | inode->i_fop = files[i].ops; | 1162 | inode->i_fop = files[i].ops; |
1180 | d_add(dentry, inode); | 1163 | d_add(dentry, inode); |
1181 | } | 1164 | } |
1182 | out: | 1165 | out: |
1183 | return ret; | 1166 | return ret; |
1184 | err: | ||
1185 | d_genocide(dir); | ||
1186 | goto out; | ||
1187 | } | 1167 | } |
1188 | 1168 | ||
1189 | static int sel_make_dir(struct super_block *sb, struct dentry *dentry) | 1169 | static int sel_make_dir(struct inode *dir, struct dentry *dentry) |
1190 | { | 1170 | { |
1191 | int ret = 0; | 1171 | int ret = 0; |
1192 | struct inode *inode; | 1172 | struct inode *inode; |
1193 | 1173 | ||
1194 | inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); | 1174 | inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO); |
1195 | if (!inode) { | 1175 | if (!inode) { |
1196 | ret = -ENOMEM; | 1176 | ret = -ENOMEM; |
1197 | goto out; | 1177 | goto out; |
1198 | } | 1178 | } |
1199 | inode->i_op = &simple_dir_inode_operations; | 1179 | inode->i_op = &simple_dir_inode_operations; |
1200 | inode->i_fop = &simple_dir_operations; | 1180 | inode->i_fop = &simple_dir_operations; |
1181 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
1182 | inode->i_nlink++; | ||
1201 | d_add(dentry, inode); | 1183 | d_add(dentry, inode); |
1184 | /* bump link count on parent directory, too */ | ||
1185 | dir->i_nlink++; | ||
1202 | out: | 1186 | out: |
1203 | return ret; | 1187 | return ret; |
1204 | } | 1188 | } |
@@ -1207,7 +1191,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) | |||
1207 | { | 1191 | { |
1208 | int ret; | 1192 | int ret; |
1209 | struct dentry *dentry; | 1193 | struct dentry *dentry; |
1210 | struct inode *inode; | 1194 | struct inode *inode, *root_inode; |
1211 | struct inode_security_struct *isec; | 1195 | struct inode_security_struct *isec; |
1212 | 1196 | ||
1213 | static struct tree_descr selinux_files[] = { | 1197 | static struct tree_descr selinux_files[] = { |
@@ -1228,30 +1212,33 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) | |||
1228 | }; | 1212 | }; |
1229 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); | 1213 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
1230 | if (ret) | 1214 | if (ret) |
1231 | return ret; | 1215 | goto err; |
1216 | |||
1217 | root_inode = sb->s_root->d_inode; | ||
1232 | 1218 | ||
1233 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); | 1219 | dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); |
1234 | if (!dentry) | 1220 | if (!dentry) { |
1235 | return -ENOMEM; | 1221 | ret = -ENOMEM; |
1222 | goto err; | ||
1223 | } | ||
1236 | 1224 | ||
1237 | inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); | 1225 | ret = sel_make_dir(root_inode, dentry); |
1238 | if (!inode) | ||
1239 | goto out; | ||
1240 | inode->i_op = &simple_dir_inode_operations; | ||
1241 | inode->i_fop = &simple_dir_operations; | ||
1242 | d_add(dentry, inode); | ||
1243 | bool_dir = dentry; | ||
1244 | ret = sel_make_bools(); | ||
1245 | if (ret) | 1226 | if (ret) |
1246 | goto out; | 1227 | goto err; |
1228 | |||
1229 | bool_dir = dentry; | ||
1247 | 1230 | ||
1248 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); | 1231 | dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); |
1249 | if (!dentry) | 1232 | if (!dentry) { |
1250 | return -ENOMEM; | 1233 | ret = -ENOMEM; |
1234 | goto err; | ||
1235 | } | ||
1251 | 1236 | ||
1252 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); | 1237 | inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); |
1253 | if (!inode) | 1238 | if (!inode) { |
1254 | goto out; | 1239 | ret = -ENOMEM; |
1240 | goto err; | ||
1241 | } | ||
1255 | isec = (struct inode_security_struct*)inode->i_security; | 1242 | isec = (struct inode_security_struct*)inode->i_security; |
1256 | isec->sid = SECINITSID_DEVNULL; | 1243 | isec->sid = SECINITSID_DEVNULL; |
1257 | isec->sclass = SECCLASS_CHR_FILE; | 1244 | isec->sclass = SECCLASS_CHR_FILE; |
@@ -1262,22 +1249,23 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) | |||
1262 | selinux_null = dentry; | 1249 | selinux_null = dentry; |
1263 | 1250 | ||
1264 | dentry = d_alloc_name(sb->s_root, "avc"); | 1251 | dentry = d_alloc_name(sb->s_root, "avc"); |
1265 | if (!dentry) | 1252 | if (!dentry) { |
1266 | return -ENOMEM; | 1253 | ret = -ENOMEM; |
1254 | goto err; | ||
1255 | } | ||
1267 | 1256 | ||
1268 | ret = sel_make_dir(sb, dentry); | 1257 | ret = sel_make_dir(root_inode, dentry); |
1269 | if (ret) | 1258 | if (ret) |
1270 | goto out; | 1259 | goto err; |
1271 | 1260 | ||
1272 | ret = sel_make_avc_files(dentry); | 1261 | ret = sel_make_avc_files(dentry); |
1273 | if (ret) | 1262 | if (ret) |
1274 | goto out; | 1263 | goto err; |
1275 | |||
1276 | return 0; | ||
1277 | out: | 1264 | out: |
1278 | dput(dentry); | 1265 | return ret; |
1266 | err: | ||
1279 | printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); | 1267 | printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); |
1280 | return -ENOMEM; | 1268 | goto out; |
1281 | } | 1269 | } |
1282 | 1270 | ||
1283 | static struct super_block *sel_get_sb(struct file_system_type *fs_type, | 1271 | static struct super_block *sel_get_sb(struct file_system_type *fs_type, |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8a764928ff4b..63e0b7f29cb5 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -27,7 +27,8 @@ | |||
27 | #include <linux/in.h> | 27 | #include <linux/in.h> |
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | #include <linux/audit.h> | 29 | #include <linux/audit.h> |
30 | #include <asm/semaphore.h> | 30 | #include <linux/mutex.h> |
31 | |||
31 | #include "flask.h" | 32 | #include "flask.h" |
32 | #include "avc.h" | 33 | #include "avc.h" |
33 | #include "avc_ss.h" | 34 | #include "avc_ss.h" |
@@ -48,9 +49,9 @@ static DEFINE_RWLOCK(policy_rwlock); | |||
48 | #define POLICY_RDUNLOCK read_unlock(&policy_rwlock) | 49 | #define POLICY_RDUNLOCK read_unlock(&policy_rwlock) |
49 | #define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock) | 50 | #define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock) |
50 | 51 | ||
51 | static DECLARE_MUTEX(load_sem); | 52 | static DEFINE_MUTEX(load_mutex); |
52 | #define LOAD_LOCK down(&load_sem) | 53 | #define LOAD_LOCK mutex_lock(&load_mutex) |
53 | #define LOAD_UNLOCK up(&load_sem) | 54 | #define LOAD_UNLOCK mutex_unlock(&load_mutex) |
54 | 55 | ||
55 | static struct sidtab sidtab; | 56 | static struct sidtab sidtab; |
56 | struct policydb policydb; | 57 | struct policydb policydb; |