Overview
About vulnerability
In the Linux kernel, the following vulnerability has been resolved:
rbd: eliminate a race in lock_dwork draining on unmap
Given how rbd_lock_add_request() and rbd_img_exclusive_lock() are written, lock_dwork may be (re)queued more than it’s actually needed: for example in case a new I/O request comes in while we are in the middle of rbd_acquire_lock() on behalf of another I/O request. This is expected and with rbd_release_lock() preemptively canceling lock_dwork is benign under normal operation.
A more problematic example is maybe_kick_acquire():
if (have_requests || delayed_work_pending(&rbd_dev->lock_dwork)) { dout("%s rbd_dev %p kicking lock_dwork\n", func, rbd_dev); mod_delayed_work(rbd_dev->task_wq, &rbd_dev->lock_dwork, 0); }
It’s not unrealistic for lock_dwork to get canceled right after delayed_work_pending() returns true and for mod_delayed_work() to requeue it right there anyway. This is a classic TOCTOU race.
When it comes to unmapping the image, there is an implicit assumption of no self-initiated exclusive lock activity past the point of return from rbd_dev_image_unlock() which unlocks the lock if it happens to be held. This unlock is assumed to be final and lock_dwork (as well as all other exclusive lock tasks, really) isn’t expected to get queued again. However, lock_dwork is canceled only in cancel_tasks_sync() (i.e. later in the unmap sequence) and on top of that the cancellation can get in effect nullified by maybe_kick_acquire(). This may result in rbd_acquire_lock() executing after rbd_dev_device_release() and rbd_dev_image_release() run and free and/or reset a bunch of things. One of the possible failure modes then is a violated
rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
in rbd_dev_header_info() which is called via rbd_dev_refresh() from rbd_post_acquire_action().
Redo exclusive lock task draining to provide saner semantics and try to meet the assumptions around rbd_dev_image_unlock().
Details
- Affected product:
- AlmaLinux 9.2 ESU , Amazon Linux 2 ELS , CentOS 7 ELS , CentOS 8.4 ELS , CentOS 8.5 ELS , CentOS Stream 8 ELS , Debian 10 ELS , Oracle Linux 7 ELS , RHEL 7 ELS , TuxCare 9.6 ESU , Ubuntu 16.04 ELS , Ubuntu 18.04 ELS , Ubuntu 20.04 ELS
- Affected packages:
- kernel @ 5.14.0 (+12 more)