Skip to content

Commit 342c966

Browse files
riteshharjanigregkh
authored andcommitted
pseries/papr-hvpipe: Fix race with interrupt handler
commit 7a4f084 upstream. While executing ->ioctl handler or ->release handler, if an interrupt fires on the same cpu, then we can enter into a deadlock. This patch fixes both these handlers to take spin_lock_irq{save|restore} versions of the lock to prevent this deadlock. Cc: stable@vger.kernel.org Fixes: 814ef09 ("powerpc/pseries: Add papr-hvpipe char driver for HVPIPE interfaces") Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/e4ed435c44fc191f2eb23c7907ba6f72f193e6aa.1777606826.git.ritesh.list@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f1862db commit 342c966

1 file changed

Lines changed: 11 additions & 9 deletions

File tree

arch/powerpc/platforms/pseries/papr-hvpipe.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -444,13 +444,14 @@ static int papr_hvpipe_handle_release(struct inode *inode,
444444
struct file *file)
445445
{
446446
struct hvpipe_source_info *src_info;
447+
unsigned long flags;
447448

448449
/*
449450
* Hold the lock, remove source from src_list, reset the
450451
* hvpipe status and release the lock to prevent any race
451452
* with message event IRQ.
452453
*/
453-
spin_lock(&hvpipe_src_list_lock);
454+
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
454455
src_info = file->private_data;
455456
list_del(&src_info->list);
456457
file->private_data = NULL;
@@ -461,10 +462,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,
461462
*/
462463
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
463464
src_info->hvpipe_status = 0;
464-
spin_unlock(&hvpipe_src_list_lock);
465+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
465466
hvpipe_rtas_recv_msg(NULL, 0);
466467
} else
467-
spin_unlock(&hvpipe_src_list_lock);
468+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
468469

469470
kfree(src_info);
470471
return 0;
@@ -480,20 +481,21 @@ static const struct file_operations papr_hvpipe_handle_ops = {
480481
static int papr_hvpipe_dev_create_handle(u32 srcID)
481482
{
482483
struct hvpipe_source_info *src_info __free(kfree) = NULL;
484+
unsigned long flags;
483485

484-
spin_lock(&hvpipe_src_list_lock);
486+
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
485487
/*
486488
* Do not allow more than one process communicates with
487489
* each source.
488490
*/
489491
src_info = hvpipe_find_source(srcID);
490492
if (src_info) {
491-
spin_unlock(&hvpipe_src_list_lock);
493+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
492494
pr_err("pid(%d) is already using the source(%d)\n",
493495
src_info->tsk->pid, srcID);
494496
return -EALREADY;
495497
}
496-
spin_unlock(&hvpipe_src_list_lock);
498+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
497499

498500
src_info = kzalloc_obj(*src_info, GFP_KERNEL_ACCOUNT);
499501
if (!src_info)
@@ -510,18 +512,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
510512
return fdf.err;
511513

512514
retain_and_null_ptr(src_info);
513-
spin_lock(&hvpipe_src_list_lock);
515+
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
514516
/*
515517
* If two processes are executing ioctl() for the same
516518
* source ID concurrently, prevent the second process to
517519
* acquire FD.
518520
*/
519521
if (hvpipe_find_source(srcID)) {
520-
spin_unlock(&hvpipe_src_list_lock);
522+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
521523
return -EALREADY;
522524
}
523525
list_add(&src_info->list, &hvpipe_src_list);
524-
spin_unlock(&hvpipe_src_list_lock);
526+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
525527
return fd_publish(fdf);
526528
}
527529

0 commit comments

Comments
 (0)