net: FIX bonding sysfs rtnl_lock deadlock
authorEric W. Biederman <ebiederm@xmission.com>
Wed, 13 May 2009 17:02:50 +0000 (17:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 19 May 2009 05:16:00 +0000 (22:16 -0700)
Sysfs files for a network device can not unconditionally take the
rtnl_lock as the bonding sysfs files do.  If someone accesses those
sysfs files while the network device is being unregistered with the
rtnl_lock held we will deadlock.

So use trylock and restart_syscall to avoid this problem.

Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bonding/bond_sysfs.c

index d287315..3a1b7b0 100644 (file)
@@ -251,7 +251,8 @@ static ssize_t bonding_store_slaves(struct device *d,
 
        /* Note:  We can't hold bond->lock here, as bond_create grabs it. */
 
-       rtnl_lock();
+       if (!rtnl_trylock())
+               return restart_syscall();
        down_write(&(bonding_rwsem));
 
        sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
@@ -1171,7 +1172,8 @@ static ssize_t bonding_store_primary(struct device *d,
        struct slave *slave;
        struct bonding *bond = to_bond(d);
 
-       rtnl_lock();
+       if (!rtnl_trylock())
+               return restart_syscall();
        read_lock(&bond->lock);
        write_lock_bh(&bond->curr_slave_lock);
 
@@ -1288,7 +1290,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
         struct slave *new_active = NULL;
        struct bonding *bond = to_bond(d);
 
-       rtnl_lock();
+       if (!rtnl_trylock())
+               return restart_syscall();
        read_lock(&bond->lock);
        write_lock_bh(&bond->curr_slave_lock);