[Devel] [PATCH rh7] ploop: add support for dm-crypted ploops

Andrey Ryabinin aryabinin at virtuozzo.com
Fri Aug 19 03:44:36 PDT 2016



On 08/19/2016 02:40 AM, Maxim Patlasov wrote:
> On 08/18/2016 09:49 AM, Andrey Ryabinin wrote:
> 
>>
>> On 08/18/2016 04:21 AM, Maxim Patlasov wrote:
>>> Andrey,
>>>
>>>
>>> ploop_freeze() must use __ploop_get_dm_crypt_bdev(), not ploop_get_dm_crypt_bdev()!
>>>
>> YUp.
>>
>>> Another problem is that the patch does not ensure that plo->dm_crypt_bdev stays the same between PLOOP_IOC_FREEZE/THAW. I could easily get:
>>>
>>> [  636.600190] BUG: unable to handle kernel NULL pointer dereference at 0000000000000068
>>> [  636.600934] IP: [<ffffffff810ac5d3>] up_read+0x13/0x30
>>> [  636.601446] PGD 222f5a067 PUD 224bc6067 PMD 0
>>> [  636.601915] Oops: 0002 [#1] SMP
>>> ...
>>>
>>> [  636.623264] Call Trace:
>>> [  636.623597]  [<ffffffff811fd346>] drop_super+0x16/0x30
>>> [  636.624104]  [<ffffffff81237010>] freeze_bdev+0x60/0xe0
>>> [  636.624627]  [<ffffffffa0541a3e>] ploop_ioctl+0x2b8e/0x2c80 [ploop]
>>> [  636.625237]  [<ffffffff811acb44>] ? handle_mm_fault+0x5b4/0xf50
>>> [  636.625822]  [<ffffffff812d41ef>] blkdev_ioctl+0x2df/0x770
>>> [  636.626439]  [<ffffffff812365d1>] block_ioctl+0x41/0x50
>>> [  636.627162]  [<ffffffff8120d515>] do_vfs_ioctl+0x255/0x4f0
>>> [  636.627827]  [<ffffffff8120d804>] SyS_ioctl+0x54/0xa0
>>>
>>> due to this problem.
>> I don't see direct relation between this crash and changing plo->dm_crypt_bdev in between freeze/thaw.
> 
> In ideal world freeze+thaw+freeze+thaw must change bd_fsfreeze_count like this: 0 --> 1 --> 0 --> 1 --> 0. But if plo->dm_crypt_bdev changes in between, the first increment may be applied to one bdev, then decrement to another bdev, then the second increment again to the first bdev.
> 
>>
>> The way I read this
>>
>> struct super_block *freeze_bdev(struct block_device *bdev)
>> ...
>>     if (++bdev->bd_fsfreeze_count > 1) {
>>
>>         sb = get_super(bdev);  // this returned NULL, so we don't have active super block on this device.
>>         drop_super(sb); // NULL ptr deref
>>         mutex_unlock(&bdev->bd_fsfreeze_mutex);
>>         return sb;
>>     
>>
>> AFAIU, this can happen if we call freeze_bdev() twice on block device which doesn't have mounted fs.
>> Isn't this a bug in freeze_bdev()?
> 
> No. The bug is to call freeze_bdev second time if the first time it returned sb == NULL.
> 

Disagreed. This would mean that all callers supposed to synchronize freeze_bdev()/thaw_bdev() sequence.
Otherwise we can get:

CPU 0:					CPU1:
	freeze_bdev() //return NULL
					freeze_bdev() //NULL-ptr deref
					thaw_bdev()
	thaw_bdev()

So, how do you propose to fix that case? If freeze_bdev() on CPU1 is illegal, that would mean that every freeze_bdev()...thaw_bdev() should
be in critical section, iow surrounded by some per-bdev lock. While comment near freeze_bdev() says that it totally ok if multiple freeze
request arrive simultaneously.

Note, that this patch is also still affected by this bug, e.g.:
	1) cryptsetup open /dev/ploop0p1 test
	2) freeze ploop
	3) dmsetup suspend test //suspend calls lock_fs()->freeze_bdev() -> NULL ptr deref


So the only sane way to fix this is to add NULL check before drop_super().









More information about the Devel mailing list