mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-06-07 17:46:15 +00:00
dm: protect pthread_cond_wait() against spurious wakeups
Users of pthread_cond_wait() should take care of spurious wakeups and it is usually used in conjunction with a predicate. Not doing so can result in unintended behavior. For example: virtio_net_tx_thread(): entry -> pthread_cond_wait() -> spurious wakeup -> vq_clear_used_ring_flags() -> segfault (vq->used uninitialized) tpm_crb_request_deliver(): entry -> pthread_cond_wait() -> spurious wakeup -> swtpm_handle_request() called needlessly virtio_rnd_get_entropy(): entry -> pthread_cond_wait() -> spurious wakeup -> no avail ring processing -> virtio_rnd_notify() skips pthread_cond_signal() due to rnd->in_progress -> vq_endchains() called needlessly -> wait in pthread_cond_wait() indefinitely Fix these uses of pthread_cond_wait() by using predicates. The only use case without a clear predicate is the tx thread in virtio-mei, because it works with two-dimensional linked lists. v1 -> v2: - fix bugs and comments - reduce code redundancy Tracked-On: #2763 Signed-off-by: Peter Fang <peter.fang@intel.com> Reviewed-by: Shuo A Liu <shuo.a.liu@intel.com>
This commit is contained in:
@@ -265,7 +265,12 @@ static void tpm_crb_request_deliver(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pthread_cond_wait(&tpm_vdev->request_cond, &tpm_vdev->request_mutex);
|
||||
while (!ret &&
|
||||
tpm_vdev->crb_regs.regs.ctrl_start == CRB_CTRL_CMD_COMPLETED) {
|
||||
ret = pthread_cond_wait(
|
||||
&tpm_vdev->request_cond, &tpm_vdev->request_mutex);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
DPRINTF("ERROR: Failed to wait condition(%d)\n", ret);
|
||||
break;
|
||||
@@ -312,6 +317,11 @@ static void crb_reg_write(struct tpm_crb_vdev *tpm_vdev, uint64_t addr, int size
|
||||
(tpm_vdev->crb_regs.regs.ctrl_sts.tpmIdle != 1) &&
|
||||
(get_active_locality(tpm_vdev) == target_loc)) {
|
||||
|
||||
if (pthread_mutex_lock(&tpm_vdev->request_mutex)) {
|
||||
DPRINTF("ERROR: Failed to acquire mutex lock\n");
|
||||
break;
|
||||
}
|
||||
|
||||
tpm_vdev->crb_regs.regs.ctrl_start = CRB_CTRL_START_CMD;
|
||||
cmd_size = MIN(get_tpm_cmd_size(tpm_vdev->data_buffer),
|
||||
TPM_CRB_DATA_BUFFER_SIZE);
|
||||
@@ -322,11 +332,6 @@ static void crb_reg_write(struct tpm_crb_vdev *tpm_vdev, uint64_t addr, int size
|
||||
tpm_vdev->cmd.out = &tpm_vdev->data_buffer[0];
|
||||
tpm_vdev->cmd.out_len = TPM_CRB_DATA_BUFFER_SIZE;
|
||||
|
||||
if (pthread_mutex_lock(&tpm_vdev->request_mutex)) {
|
||||
DPRINTF("ERROR: Failed to acquire mutex lock\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (pthread_cond_signal(&tpm_vdev->request_cond)) {
|
||||
DPRINTF("ERROR: Failed to wait condition\n");
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user