aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/configfs/dir.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index a89058b39884..7a8db78a91d2 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1100,7 +1100,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1100 struct configfs_subsystem *subsys; 1100 struct configfs_subsystem *subsys;
1101 struct configfs_dirent *sd; 1101 struct configfs_dirent *sd;
1102 struct config_item_type *type; 1102 struct config_item_type *type;
1103 struct module *owner = NULL; 1103 struct module *subsys_owner = NULL, *new_item_owner = NULL;
1104 char *name; 1104 char *name;
1105 1105
1106 if (dentry->d_parent == configfs_sb->s_root) { 1106 if (dentry->d_parent == configfs_sb->s_root) {
@@ -1137,10 +1137,25 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1137 goto out_put; 1137 goto out_put;
1138 } 1138 }
1139 1139
1140 /*
1141 * The subsystem may belong to a different module than the item
1142 * being created. We don't want to safely pin the new item but
1143 * fail to pin the subsystem it sits under.
1144 */
1145 if (!subsys->su_group.cg_item.ci_type) {
1146 ret = -EINVAL;
1147 goto out_put;
1148 }
1149 subsys_owner = subsys->su_group.cg_item.ci_type->ct_owner;
1150 if (!try_module_get(subsys_owner)) {
1151 ret = -EINVAL;
1152 goto out_put;
1153 }
1154
1140 name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); 1155 name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
1141 if (!name) { 1156 if (!name) {
1142 ret = -ENOMEM; 1157 ret = -ENOMEM;
1143 goto out_put; 1158 goto out_subsys_put;
1144 } 1159 }
1145 1160
1146 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); 1161 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
@@ -1172,7 +1187,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1172 * If ret != 0, then link_obj() was never called. 1187 * If ret != 0, then link_obj() was never called.
1173 * There are no extra references to clean up. 1188 * There are no extra references to clean up.
1174 */ 1189 */
1175 goto out_put; 1190 goto out_subsys_put;
1176 } 1191 }
1177 1192
1178 /* 1193 /*
@@ -1186,8 +1201,8 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
1186 goto out_unlink; 1201 goto out_unlink;
1187 } 1202 }
1188 1203
1189 owner = type->ct_owner; 1204 new_item_owner = type->ct_owner;
1190 if (!try_module_get(owner)) { 1205 if (!try_module_get(new_item_owner)) {
1191 ret = -EINVAL; 1206 ret = -EINVAL;
1192 goto out_unlink; 1207 goto out_unlink;
1193 } 1208 }
@@ -1236,9 +1251,13 @@ out_unlink:
1236 mutex_unlock(&subsys->su_mutex); 1251 mutex_unlock(&subsys->su_mutex);
1237 1252
1238 if (module_got) 1253 if (module_got)
1239 module_put(owner); 1254 module_put(new_item_owner);
1240 } 1255 }
1241 1256
1257out_subsys_put:
1258 if (ret)
1259 module_put(subsys_owner);
1260
1242out_put: 1261out_put:
1243 /* 1262 /*
1244 * link_obj()/link_group() took a reference from child->parent, 1263 * link_obj()/link_group() took a reference from child->parent,
@@ -1257,7 +1276,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1257 struct config_item *item; 1276 struct config_item *item;
1258 struct configfs_subsystem *subsys; 1277 struct configfs_subsystem *subsys;
1259 struct configfs_dirent *sd; 1278 struct configfs_dirent *sd;
1260 struct module *owner = NULL; 1279 struct module *subsys_owner = NULL, *dead_item_owner = NULL;
1261 int ret; 1280 int ret;
1262 1281
1263 if (dentry->d_parent == configfs_sb->s_root) 1282 if (dentry->d_parent == configfs_sb->s_root)
@@ -1284,6 +1303,10 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1284 return -EINVAL; 1303 return -EINVAL;
1285 } 1304 }
1286 1305
1306 /* configfs_mkdir() shouldn't have allowed this */
1307 BUG_ON(!subsys->su_group.cg_item.ci_type);
1308 subsys_owner = subsys->su_group.cg_item.ci_type->ct_owner;
1309
1287 /* 1310 /*
1288 * Ensure that no racing symlink() will make detach_prep() fail while 1311 * Ensure that no racing symlink() will make detach_prep() fail while
1289 * the new link is temporarily attached 1312 * the new link is temporarily attached
@@ -1321,7 +1344,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1321 config_item_put(parent_item); 1344 config_item_put(parent_item);
1322 1345
1323 if (item->ci_type) 1346 if (item->ci_type)
1324 owner = item->ci_type->ct_owner; 1347 dead_item_owner = item->ci_type->ct_owner;
1325 1348
1326 if (sd->s_type & CONFIGFS_USET_DIR) { 1349 if (sd->s_type & CONFIGFS_USET_DIR) {
1327 configfs_detach_group(item); 1350 configfs_detach_group(item);
@@ -1343,7 +1366,8 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
1343 /* Drop our reference from above */ 1366 /* Drop our reference from above */
1344 config_item_put(item); 1367 config_item_put(item);
1345 1368
1346 module_put(owner); 1369 module_put(dead_item_owner);
1370 module_put(subsys_owner);
1347 1371
1348 return 0; 1372 return 0;
1349} 1373}