diff options
| author | Jeff Garzik <jeff@garzik.org> | 2006-03-22 19:13:54 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-03-22 19:13:54 -0500 |
| commit | f01c18456993bab43067b678f56c87ca954aa43b (patch) | |
| tree | 3e0cd0cdf1a57618202b46a7126125902e3ab832 /security/selinux/selinuxfs.c | |
| parent | 949ec2c8e6b7b89179b85baf6309c009e1a1b951 (diff) | |
| parent | 1c2e02750b992703a8a18634e08b04353face243 (diff) | |
Merge branch 'master'
Diffstat (limited to 'security/selinux/selinuxfs.c')
| -rw-r--r-- | security/selinux/selinuxfs.c | 112 |
1 files changed, 50 insertions, 62 deletions
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, |
