RDS: have sockets get transport module references
Right now there's nothing to stop the various paths that use rs->rs_transport from racing with rmmod and executing freed transport code. The simple fix is to have binding to a transport also hold a reference to the transport's module, removing this class of races. We already had an unused t_owner field which was set for the modular transports and which wasn't set for the built-in loop transport. Signed-off-by: Zach Brown <zach.brown@oracle.com>
Цей коміт міститься в:
@@ -71,19 +71,28 @@ void rds_trans_unregister(struct rds_transport *trans)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rds_trans_unregister);
|
||||
|
||||
void rds_trans_put(struct rds_transport *trans)
|
||||
{
|
||||
if (trans && trans->t_owner)
|
||||
module_put(trans->t_owner);
|
||||
}
|
||||
|
||||
struct rds_transport *rds_trans_get_preferred(__be32 addr)
|
||||
{
|
||||
struct rds_transport *ret = NULL;
|
||||
int i;
|
||||
struct rds_transport *trans;
|
||||
unsigned int i;
|
||||
|
||||
if (IN_LOOPBACK(ntohl(addr)))
|
||||
return &rds_loop_transport;
|
||||
|
||||
down_read(&rds_trans_sem);
|
||||
for (i = 0; i < RDS_TRANS_COUNT; i++)
|
||||
{
|
||||
if (transports[i] && (transports[i]->laddr_check(addr) == 0)) {
|
||||
ret = transports[i];
|
||||
for (i = 0; i < RDS_TRANS_COUNT; i++) {
|
||||
trans = transports[i];
|
||||
|
||||
if (trans && (trans->laddr_check(addr) == 0) &&
|
||||
(!trans->t_owner || try_module_get(trans->t_owner))) {
|
||||
ret = trans;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Посилання в новій задачі
Заблокувати користувача