ieee1394: raw1394: prevent unloading of low-level driver
Unloading the low-level driver module of a FireWire host can lead to all sorts of trouble if a raw1394 userspace client is using the host. Just disallow it by incrementing the LLD's module reference count on a RAW1394_REQ_SET_CARD write operation. Decrement it when the file is closed. This feature wouldn't be relevant if "modprobe -r video1394" or "modprobe -r dv1394" didn't automatically unload ohci1394 too. http://bugzilla.kernel.org/show_bug.cgi?id=7701 Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Dan Dennedy <dan@dennedy.org>
This commit is contained in:
parent
12ba145c94
commit
0fe4c6fcac
@ -636,27 +636,32 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
|
|||||||
|
|
||||||
case RAW1394_REQ_SET_CARD:
|
case RAW1394_REQ_SET_CARD:
|
||||||
spin_lock_irqsave(&host_info_lock, flags);
|
spin_lock_irqsave(&host_info_lock, flags);
|
||||||
if (req->req.misc < host_count) {
|
if (req->req.misc >= host_count) {
|
||||||
list_for_each_entry(hi, &host_info_list, list) {
|
|
||||||
if (!req->req.misc--)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
get_device(&hi->host->device); // XXX Need to handle failure case
|
|
||||||
list_add_tail(&fi->list, &hi->file_info_list);
|
|
||||||
fi->host = hi->host;
|
|
||||||
fi->state = connected;
|
|
||||||
|
|
||||||
req->req.error = RAW1394_ERROR_NONE;
|
|
||||||
req->req.generation = get_hpsb_generation(fi->host);
|
|
||||||
req->req.misc = (fi->host->node_id << 16)
|
|
||||||
| fi->host->node_count;
|
|
||||||
if (fi->protocol_version > 3) {
|
|
||||||
req->req.misc |=
|
|
||||||
NODEID_TO_NODE(fi->host->irm_id) << 8;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
req->req.error = RAW1394_ERROR_INVALID_ARG;
|
req->req.error = RAW1394_ERROR_INVALID_ARG;
|
||||||
|
goto out_set_card;
|
||||||
}
|
}
|
||||||
|
list_for_each_entry(hi, &host_info_list, list)
|
||||||
|
if (!req->req.misc--)
|
||||||
|
break;
|
||||||
|
get_device(&hi->host->device); /* FIXME handle failure case */
|
||||||
|
list_add_tail(&fi->list, &hi->file_info_list);
|
||||||
|
|
||||||
|
/* prevent unloading of the host's low-level driver */
|
||||||
|
if (!try_module_get(hi->host->driver->owner)) {
|
||||||
|
req->req.error = RAW1394_ERROR_ABORTED;
|
||||||
|
goto out_set_card;
|
||||||
|
}
|
||||||
|
WARN_ON(fi->host);
|
||||||
|
fi->host = hi->host;
|
||||||
|
fi->state = connected;
|
||||||
|
|
||||||
|
req->req.error = RAW1394_ERROR_NONE;
|
||||||
|
req->req.generation = get_hpsb_generation(fi->host);
|
||||||
|
req->req.misc = (fi->host->node_id << 16)
|
||||||
|
| fi->host->node_count;
|
||||||
|
if (fi->protocol_version > 3)
|
||||||
|
req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
|
||||||
|
out_set_card:
|
||||||
spin_unlock_irqrestore(&host_info_lock, flags);
|
spin_unlock_irqrestore(&host_info_lock, flags);
|
||||||
|
|
||||||
req->req.length = 0;
|
req->req.length = 0;
|
||||||
@ -2955,6 +2960,11 @@ static int raw1394_release(struct inode *inode, struct file *file)
|
|||||||
put_device(&fi->host->device);
|
put_device(&fi->host->device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&host_info_lock, flags);
|
||||||
|
if (fi->host)
|
||||||
|
module_put(fi->host->driver->owner);
|
||||||
|
spin_unlock_irqrestore(&host_info_lock, flags);
|
||||||
|
|
||||||
kfree(fi);
|
kfree(fi);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user