Commit b3e76af87441fc36eef3516d73ab2314e7b2d911

Authored by Louis Rilling
Committed by Mark Fasheh
1 parent 107ed40bd0

configfs: Fix deadlock with racing rmdir() and rename()

This patch fixes the deadlock between racing sys_rename() and configfs_rmdir().

The idea is to avoid locking i_mutexes of default groups in
configfs_detach_prep(), and rely instead on the new configfs_dirent_lock to
protect against configfs_dirent's linkage mutations. To ensure that an mkdir()
racing with rmdir() will not create new items in a to-be-removed default group,
we make configfs_new_dirent() check for the CONFIGFS_USET_DROPPING flag right
before linking the new dirent, and return error if the flag is set. This makes
racing mkdir()/symlink()/dir_open() fail in places where errors could already
happen, resp. in (attach_item()|attach_group())/create_link()/new_dirent().

configfs_depend() remains safe since it locks all the path from configfs root,
and is thus mutually exclusive with rmdir().

An advantage of this is that now detach_groups() unconditionnaly takes the
default groups i_mutex, which makes it more consistent with populate_groups().

Signed-off-by: Louis Rilling <Louis.Rilling@kerlabs.com>
Signed-off-by: Joel Becker <joel.becker@oracle.com>

Showing 1 changed file with 25 additions and 20 deletions Side-by-side Diff

... ... @@ -43,6 +43,10 @@
43 43 * and configfs_dirent_lock locked, in that order.
44 44 * This allows one to safely traverse configfs_dirent trees and symlinks without
45 45 * having to lock inodes.
  46 + *
  47 + * Protects setting of CONFIGFS_USET_DROPPING: checking the flag
  48 + * unlocked is not reliable unless in detach_groups() called from
  49 + * rmdir()/unregister() and from configfs_attach_group()
46 50 */
47 51 DEFINE_SPINLOCK(configfs_dirent_lock);
48 52  
... ... @@ -91,6 +95,11 @@
91 95 INIT_LIST_HEAD(&sd->s_children);
92 96 sd->s_element = element;
93 97 spin_lock(&configfs_dirent_lock);
  98 + if (parent_sd->s_type & CONFIGFS_USET_DROPPING) {
  99 + spin_unlock(&configfs_dirent_lock);
  100 + kmem_cache_free(configfs_dir_cachep, sd);
  101 + return ERR_PTR(-ENOENT);
  102 + }
94 103 list_add(&sd->s_sibling, &parent_sd->s_children);
95 104 spin_unlock(&configfs_dirent_lock);
96 105  
... ... @@ -349,11 +358,11 @@
349 358  
350 359 /*
351 360 * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are
352   - * attributes and are removed by rmdir(). We recurse, taking i_mutex
353   - * on all children that are candidates for default detach. If the
354   - * result is clean, then configfs_detach_group() will handle dropping
355   - * i_mutex. If there is an error, the caller will clean up the i_mutex
356   - * holders via configfs_detach_rollback().
  361 + * attributes and are removed by rmdir(). We recurse, setting
  362 + * CONFIGFS_USET_DROPPING on all children that are candidates for
  363 + * default detach.
  364 + * If there is an error, the caller will reset the flags via
  365 + * configfs_detach_rollback().
357 366 */
358 367 static int configfs_detach_prep(struct dentry *dentry)
359 368 {
... ... @@ -370,8 +379,7 @@
370 379 if (sd->s_type & CONFIGFS_NOT_PINNED)
371 380 continue;
372 381 if (sd->s_type & CONFIGFS_USET_DEFAULT) {
373   - mutex_lock(&sd->s_dentry->d_inode->i_mutex);
374   - /* Mark that we've taken i_mutex */
  382 + /* Mark that we're trying to drop the group */
375 383 sd->s_type |= CONFIGFS_USET_DROPPING;
376 384  
377 385 /*
... ... @@ -392,7 +400,7 @@
392 400 }
393 401  
394 402 /*
395   - * Walk the tree, dropping i_mutex wherever CONFIGFS_USET_DROPPING is
  403 + * Walk the tree, resetting CONFIGFS_USET_DROPPING wherever it was
396 404 * set.
397 405 */
398 406 static void configfs_detach_rollback(struct dentry *dentry)
... ... @@ -403,11 +411,7 @@
403 411 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
404 412 if (sd->s_type & CONFIGFS_USET_DEFAULT) {
405 413 configfs_detach_rollback(sd->s_dentry);
406   -
407   - if (sd->s_type & CONFIGFS_USET_DROPPING) {
408   - sd->s_type &= ~CONFIGFS_USET_DROPPING;
409   - mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
410   - }
  414 + sd->s_type &= ~CONFIGFS_USET_DROPPING;
411 415 }
412 416 }
413 417 }
414 418  
... ... @@ -486,16 +490,12 @@
486 490  
487 491 child = sd->s_dentry;
488 492  
  493 + mutex_lock(&child->d_inode->i_mutex);
  494 +
489 495 configfs_detach_group(sd->s_element);
490 496 child->d_inode->i_flags |= S_DEAD;
491 497  
492   - /*
493   - * From rmdir/unregister, a configfs_detach_prep() pass
494   - * has taken our i_mutex for us. Drop it.
495   - * From mkdir/register cleanup, there is no sem held.
496   - */
497   - if (sd->s_type & CONFIGFS_USET_DROPPING)
498   - mutex_unlock(&child->d_inode->i_mutex);
  498 + mutex_unlock(&child->d_inode->i_mutex);
499 499  
500 500 d_delete(child);
501 501 dput(child);
502 502  
503 503  
... ... @@ -1181,12 +1181,15 @@
1181 1181 return -EINVAL;
1182 1182 }
1183 1183  
  1184 + spin_lock(&configfs_dirent_lock);
1184 1185 ret = configfs_detach_prep(dentry);
1185 1186 if (ret) {
1186 1187 configfs_detach_rollback(dentry);
  1188 + spin_unlock(&configfs_dirent_lock);
1187 1189 config_item_put(parent_item);
1188 1190 return ret;
1189 1191 }
  1192 + spin_unlock(&configfs_dirent_lock);
1190 1193  
1191 1194 /* Get a working ref for the duration of this function */
1192 1195 item = configfs_get_config_item(dentry);
1193 1196  
... ... @@ -1476,9 +1479,11 @@
1476 1479 mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex,
1477 1480 I_MUTEX_PARENT);
1478 1481 mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
  1482 + spin_lock(&configfs_dirent_lock);
1479 1483 if (configfs_detach_prep(dentry)) {
1480 1484 printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n");
1481 1485 }
  1486 + spin_unlock(&configfs_dirent_lock);
1482 1487 configfs_detach_group(&group->cg_item);
1483 1488 dentry->d_inode->i_flags |= S_DEAD;
1484 1489 mutex_unlock(&dentry->d_inode->i_mutex);