Skip to content

Commit 6542e18

Browse files
riteshharjanigregkh
authored andcommitted
pseries/papr-hvpipe: Fix race with interrupt handler
[ Upstream commit 7a4f084 ] 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: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 09c15bb commit 6542e18

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
@@ -449,13 +449,14 @@ static int papr_hvpipe_handle_release(struct inode *inode,
449449
struct file *file)
450450
{
451451
struct hvpipe_source_info *src_info;
452+
unsigned long flags;
452453

453454
/*
454455
* Hold the lock, remove source from src_list, reset the
455456
* hvpipe status and release the lock to prevent any race
456457
* with message event IRQ.
457458
*/
458-
spin_lock(&hvpipe_src_list_lock);
459+
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
459460
src_info = file->private_data;
460461
list_del(&src_info->list);
461462
file->private_data = NULL;
@@ -466,10 +467,10 @@ static int papr_hvpipe_handle_release(struct inode *inode,
466467
*/
467468
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
468469
src_info->hvpipe_status = 0;
469-
spin_unlock(&hvpipe_src_list_lock);
470+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
470471
hvpipe_rtas_recv_msg(NULL, 0);
471472
} else
472-
spin_unlock(&hvpipe_src_list_lock);
473+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
473474

474475
kfree(src_info);
475476
return 0;
@@ -485,20 +486,21 @@ static const struct file_operations papr_hvpipe_handle_ops = {
485486
static int papr_hvpipe_dev_create_handle(u32 srcID)
486487
{
487488
struct hvpipe_source_info *src_info __free(kfree) = NULL;
489+
unsigned long flags;
488490

489-
spin_lock(&hvpipe_src_list_lock);
491+
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
490492
/*
491493
* Do not allow more than one process communicates with
492494
* each source.
493495
*/
494496
src_info = hvpipe_find_source(srcID);
495497
if (src_info) {
496-
spin_unlock(&hvpipe_src_list_lock);
498+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
497499
pr_err("pid(%d) is already using the source(%d)\n",
498500
src_info->tsk->pid, srcID);
499501
return -EALREADY;
500502
}
501-
spin_unlock(&hvpipe_src_list_lock);
503+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
502504

503505
src_info = kzalloc(sizeof(*src_info), GFP_KERNEL_ACCOUNT);
504506
if (!src_info)
@@ -515,18 +517,18 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
515517
return fdf.err;
516518

517519
retain_and_null_ptr(src_info);
518-
spin_lock(&hvpipe_src_list_lock);
520+
spin_lock_irqsave(&hvpipe_src_list_lock, flags);
519521
/*
520522
* If two processes are executing ioctl() for the same
521523
* source ID concurrently, prevent the second process to
522524
* acquire FD.
523525
*/
524526
if (hvpipe_find_source(srcID)) {
525-
spin_unlock(&hvpipe_src_list_lock);
527+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
526528
return -EALREADY;
527529
}
528530
list_add(&src_info->list, &hvpipe_src_list);
529-
spin_unlock(&hvpipe_src_list_lock);
531+
spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
530532
return fd_publish(fdf);
531533
}
532534

0 commit comments

Comments
 (0)