Online Linux Driver Verification Service (alpha)

0008

RULE_ERROR

Driver becomes not available for unloading permanently

Summary

Once you blocked a driver using try_module_get() you should unblock it by module_put().

Description

There is a possibility to block unloading of a driver (kernel module). You might want to use it if the driver is currently in use by OS objects or user processes. However, its uncautious usage can undermine stability of the system as a whole.

Note that such calls can be nested (they increase/decrease semaphore counter internally). Therefore, you should call exactly one proceure that unblocks the driver for each preceeding blocking one. Otherwise, the driver will not be available for unloading--without any serious reason to put such a restriction.

Links:

Sample bugfix of drivers/mtd/mtd_blkdevs.c

Example

Sample error:

static int dev_open(struct inode*, struct file*)
{
    try_module_get(THIS_MODULE);
    ...
    //the absence of the module_put(THIS_MODULE) call
        return 0;
}

Sample error in drivers/mtd/mtd_blkdevs.c:

static int blktrans_open(struct block_device *bdev, fmode_t mode)
{
    struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
    struct mtd_blktrans_ops *tr = dev->tr;
    int ret = -ENODEV;

    if (!get_mtd_device(NULL, dev->mtd->index))
        goto out;

    if (!try_module_get(tr->owner))
        goto out_tr;

    /* FIXME: Locking. A hot pluggable device can go away
       (del_mtd_device can be called for it) without its module
       being unloaded. */
    dev->mtd->usecount++;

    ret = 0;
    if (tr->open && (ret = tr->open(dev))) {
        dev->mtd->usecount--;
        put_mtd_device(dev->mtd);
    out_tr:
        module_put(tr->owner);
    }
out:
    return ret;
}
  1. If try_module_get(tr->owner) == 0 then we goto label out_tr;
  2. At label out_tr we call module_put on the unloaded driver;

To fix the error we should replace:

        goto out_tr;

with

        goto out;