Skip to content

Commit 01a8e68

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: KVM: Avoid copy_*_user() with lock hold in kvm_eiointc_sw_status_access()
Function copy_from_user() and copy_to_user() may sleep because of page fault, and they cannot be called in spin_lock hold context. Here move funtcion calling of copy_from_user() and copy_to_user() out of function kvm_eiointc_sw_status_access(). Otherwise there will be possible warning such as: BUG: sleeping function called from invalid context at include/linux/uaccess.h:192 in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 6292, name: qemu-system-loo preempt_count: 1, expected: 0 RCU nest depth: 0, expected: 0 INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [<0000000000000000>] 0x0 hardirqs last disabled at (0): [<9000000004c4a554>] copy_process+0x90c/0x1d40 softirqs last enabled at (0): [<9000000004c4a554>] copy_process+0x90c/0x1d40 softirqs last disabled at (0): [<0000000000000000>] 0x0 CPU: 41 UID: 0 PID: 6292 Comm: qemu-system-loo Tainted: G W 6.17.0-rc3+ #31 PREEMPT(full) Tainted: [W]=WARN Stack : 0000000000000076 0000000000000000 9000000004c28264 9000100092ff4000 9000100092ff7b80 9000100092ff7b88 0000000000000000 9000100092ff7cc8 9000100092ff7cc0 9000100092ff7cc0 9000100092ff7a00 0000000000000001 0000000000000001 9000100092ff7b88 947d2f9216a5e8b9 900010008773d880 00000000ffff8b9f fffffffffffffffe 0000000000000ba1 fffffffffffffffe 000000000000003e 900000000825a15b 000010007ad38000 9000100092ff7ec0 0000000000000000 0000000000000000 9000000006f3ac60 9000000007252000 0000000000000000 00007ff746ff2230 0000000000000053 9000200088a021b0 0000555556c9d190 0000000000000000 9000000004c2827c 000055556cfb5f40 00000000000000b0 0000000000000007 0000000000000007 0000000000071c1d Call Trace: [<9000000004c2827c>] show_stack+0x5c/0x180 [<9000000004c20fac>] dump_stack_lvl+0x94/0xe4 [<9000000004c99c7c>] __might_resched+0x26c/0x290 [<9000000004f68968>] __might_fault+0x20/0x88 [<ffff800002311de0>] kvm_eiointc_sw_status_access.isra.0+0x88/0x380 [kvm] [<ffff8000022f8514>] kvm_device_ioctl+0x194/0x290 [kvm] [<900000000506b0d8>] sys_ioctl+0x388/0x1010 [<90000000063ed210>] do_syscall+0xb0/0x2d8 [<9000000004c25ef8>] handle_syscall+0xb8/0x158 Cc: stable@vger.kernel.org Fixes: 1ad7efa ("LoongArch: KVM: Add EIOINTC user mode read and write functions") Signed-off-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 62f1179 commit 01a8e68

File tree

1 file changed

+17
-12
lines changed

1 file changed

+17
-12
lines changed

arch/loongarch/kvm/intc/eiointc.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -527,19 +527,17 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
527527

528528
static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
529529
struct kvm_device_attr *attr,
530-
bool is_write)
530+
bool is_write, int *data)
531531
{
532532
int addr, ret = 0;
533533
unsigned long flags;
534534
void *p = NULL;
535-
void __user *data;
536535
struct loongarch_eiointc *s;
537536

538537
s = dev->kvm->arch.eiointc;
539538
addr = attr->attr;
540539
addr &= 0xffff;
541540

542-
data = (void __user *)attr->addr;
543541
switch (addr) {
544542
case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU:
545543
if (is_write)
@@ -561,13 +559,10 @@ static int kvm_eiointc_sw_status_access(struct kvm_device *dev,
561559
return -EINVAL;
562560
}
563561
spin_lock_irqsave(&s->lock, flags);
564-
if (is_write) {
565-
if (copy_from_user(p, data, 4))
566-
ret = -EFAULT;
567-
} else {
568-
if (copy_to_user(data, p, 4))
569-
ret = -EFAULT;
570-
}
562+
if (is_write)
563+
memcpy(p, data, 4);
564+
else
565+
memcpy(data, p, 4);
571566
spin_unlock_irqrestore(&s->lock, flags);
572567

573568
return ret;
@@ -589,7 +584,14 @@ static int kvm_eiointc_get_attr(struct kvm_device *dev,
589584

590585
return ret;
591586
case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
592-
return kvm_eiointc_sw_status_access(dev, attr, false);
587+
ret = kvm_eiointc_sw_status_access(dev, attr, false, &data);
588+
if (ret)
589+
return ret;
590+
591+
if (copy_to_user((void __user *)attr->addr, &data, 4))
592+
ret = -EFAULT;
593+
594+
return ret;
593595
default:
594596
return -EINVAL;
595597
}
@@ -609,7 +611,10 @@ static int kvm_eiointc_set_attr(struct kvm_device *dev,
609611

610612
return kvm_eiointc_regs_access(dev, attr, true, &data);
611613
case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS:
612-
return kvm_eiointc_sw_status_access(dev, attr, true);
614+
if (copy_from_user(&data, (void __user *)attr->addr, 4))
615+
return -EFAULT;
616+
617+
return kvm_eiointc_sw_status_access(dev, attr, true, &data);
613618
default:
614619
return -EINVAL;
615620
}

0 commit comments

Comments
 (0)