Commit ab05d4ab authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] raw driver oops fix

From: Dave Olien <dmo@osdl.org>

The raw.c character device Oopses dereferencing a NULL pointer in
bd_claim() This problem occurred after bd_claim() in block_dev.c was
modified to "claim the whole device when a partition is claimed".

raw_open() made the mistake of calling bd_claim BEFORE calling blkdev_get().
At that time, the bdev->bd_contains field has not yet been initialized. 
Switching the order allows blkdev_get() to initialize those fields before
calling bd_claim().

Also fixed up some error return paths:

igrab() should never fail under these circumstances since the caller
already has a reference to that inode through the bdev at that time.

In the event of blkdev_get() failure or set_blocksize() failure, not all
the work to unwind from the error was done.
parent 1022068b
...@@ -60,26 +60,26 @@ static int raw_open(struct inode *inode, struct file *filp) ...@@ -60,26 +60,26 @@ static int raw_open(struct inode *inode, struct file *filp)
bdev = raw_devices[minor].binding; bdev = raw_devices[minor].binding;
err = -ENODEV; err = -ENODEV;
if (bdev) { if (bdev) {
err = bd_claim(bdev, raw_open); err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
if (err) if (err)
goto out; goto out;
err = -ENODEV; igrab(bdev->bd_inode);
if (!igrab(bdev->bd_inode)) err = bd_claim(bdev, raw_open);
if (err) {
blkdev_put(bdev, BDEV_RAW);
goto out; goto out;
err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); }
err = set_blocksize(bdev, bdev_hardsect_size(bdev));
if (err) { if (err) {
bd_release(bdev); bd_release(bdev);
blkdev_put(bdev, BDEV_RAW);
goto out; goto out;
} else { }
err = set_blocksize(bdev, bdev_hardsect_size(bdev));
if (err == 0) {
filp->f_flags |= O_DIRECT; filp->f_flags |= O_DIRECT;
if (++raw_devices[minor].inuse == 1) if (++raw_devices[minor].inuse == 1)
filp->f_dentry->d_inode->i_mapping = filp->f_dentry->d_inode->i_mapping =
bdev->bd_inode->i_mapping; bdev->bd_inode->i_mapping;
} }
}
}
filp->private_data = bdev; filp->private_data = bdev;
out: out:
up(&raw_mutex); up(&raw_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment