2023-02-03 09:43:41

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 0/7] KVM: Standardize on "int" return types instead of "long"

This patch series is a follow-up from one of my patches in 2022 and
Sean's reply here:

https://lore.kernel.org/kvm/YpZu6%[email protected]/

KVM functions use "long" return values for functions that are wired up
to "struct file_operations", but otherwise use "int" return values for
functions that can return 0/-errno in order to avoid unintentional
divergences between 32-bit and 64-bit kernels. Some related functions
that are not part of a "struct file_operations" still use "long", though,
which can cause confusion or even subtle problems (see second patch).
Thus let's standardize on using "int" for return values in these functions
to avoid such problems in the future.

Thomas Huth (7):
KVM: Standardize on "int" return types instead of "long" in kvm_main.c
KVM: x86: Improve return type handling in
kvm_vm_ioctl_get_nr_mmu_pages()
KVM: Move KVM_GET_NR_MMU_PAGES into the deprecation section
KVM: PPC: Standardize on "int" return types in the powerpc KVM code
KVM: s390: Use "int" as return type for kvm_s390_get/set_skeys()
KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to
"int"
KVM: Change return type of kvm_arch_vm_ioctl() to "int"

arch/arm64/include/asm/kvm_host.h | 4 ++--
arch/arm64/kvm/arm.c | 3 +--
arch/arm64/kvm/guest.c | 4 ++--
arch/mips/kvm/mips.c | 4 ++--
arch/powerpc/include/asm/kvm_ppc.h | 14 +++++++-------
arch/powerpc/kvm/book3s_64_mmu_hv.c | 14 +++++++-------
arch/powerpc/kvm/book3s_64_vio.c | 4 ++--
arch/powerpc/kvm/book3s_hv.c | 6 +++---
arch/powerpc/kvm/book3s_pr.c | 4 ++--
arch/powerpc/kvm/powerpc.c | 5 ++---
arch/riscv/kvm/vm.c | 3 +--
arch/s390/kvm/kvm-s390.c | 7 +++----
arch/x86/kvm/x86.c | 8 +++++---
include/linux/kvm_host.h | 3 +--
include/uapi/linux/kvm.h | 3 ++-
virt/kvm/kvm_main.c | 4 ++--
16 files changed, 44 insertions(+), 46 deletions(-)

--
2.31.1



2023-02-03 09:43:50

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 3/7] KVM: Move KVM_GET_NR_MMU_PAGES into the deprecation section

The KVM_GET_NR_MMU_PAGES ioctl is quite questionable on 64-bit hosts
since it fails to return the full 64 bits of the value that can be
set with the corresponding KVM_SET_NR_MMU_PAGES call. This ioctl
likely has also never really been used by userspace applications
(at least not by QEMU and kvmtool which I checked), so it's better
to move it to the deprecation section in kvm.h to make it clear for
developers that this also should not be used in new code in the
future anymore.

Signed-off-by: Thomas Huth <[email protected]>
---
include/uapi/linux/kvm.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 55155e262646..f55965a4cec7 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -83,6 +83,8 @@ struct kvm_debug_guest {

#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)

+#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
+
/* *** End of deprecated interfaces *** */


@@ -1442,7 +1444,6 @@ struct kvm_vfio_spapr_tce {
#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
-#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
struct kvm_userspace_memory_region)
#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
--
2.31.1


2023-02-03 09:44:02

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 5/7] KVM: s390: Use "int" as return type for kvm_s390_get/set_skeys()

These two functions only return normal integers, so it does not
make sense to declare the return type as "long" here.

Signed-off-by: Thomas Huth <[email protected]>
---
arch/s390/kvm/kvm-s390.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index e4890e04b210..8ad1972b8a73 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1992,7 +1992,7 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
return ret;
}

-static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
+static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
{
uint8_t *keys;
uint64_t hva;
@@ -2040,7 +2040,7 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
return r;
}

-static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
+static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
{
uint8_t *keys;
uint64_t hva;
--
2.31.1


2023-02-03 09:44:05

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 4/7] KVM: PPC: Standardize on "int" return types in the powerpc KVM code

Most functions that are related to kvm_arch_vm_ioctl() already use
"int" as return type to pass error values back to the caller. Some
outlier functions use "long" instead for no good reason (they do not
really require long values here). Let's standardize on "int" here to
avoid casting the values back and forth between the two types.

Signed-off-by: Thomas Huth <[email protected]>
---
arch/powerpc/include/asm/kvm_ppc.h | 14 +++++++-------
arch/powerpc/kvm/book3s_64_mmu_hv.c | 14 +++++++-------
arch/powerpc/kvm/book3s_64_vio.c | 4 ++--
arch/powerpc/kvm/book3s_hv.c | 6 +++---
arch/powerpc/kvm/book3s_pr.c | 4 ++--
5 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index eae9619b6190..41ab4ebdc1ee 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -157,7 +157,7 @@ extern void kvmppc_map_magic(struct kvm_vcpu *vcpu);

extern int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order);
extern void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info);
-extern long kvmppc_alloc_reset_hpt(struct kvm *kvm, int order);
+extern int kvmppc_alloc_reset_hpt(struct kvm *kvm, int order);
extern void kvmppc_free_hpt(struct kvm_hpt_info *info);
extern void kvmppc_rmap_reset(struct kvm *kvm);
extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
@@ -171,7 +171,7 @@ extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm);
extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm);
extern void kvmppc_setup_partition_table(struct kvm *kvm);

-extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
+extern int kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
struct kvm_create_spapr_tce_64 *args);
#define kvmppc_ioba_validate(stt, ioba, npages) \
(iommu_tce_check_ioba((stt)->page_shift, (stt)->offset, \
@@ -212,10 +212,10 @@ extern void kvmppc_bookehv_exit(void);
extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);

extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *);
-extern long kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
- struct kvm_ppc_resize_hpt *rhpt);
-extern long kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
+extern int kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
struct kvm_ppc_resize_hpt *rhpt);
+extern int kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
+ struct kvm_ppc_resize_hpt *rhpt);

int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);

@@ -287,8 +287,8 @@ struct kvmppc_ops {
int (*emulate_mtspr)(struct kvm_vcpu *vcpu, int sprn, ulong spr_val);
int (*emulate_mfspr)(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val);
void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu);
- long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl,
- unsigned long arg);
+ int (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl,
+ unsigned long arg);
int (*hcall_implemented)(unsigned long hcall);
int (*irq_bypass_add_producer)(struct irq_bypass_consumer *,
struct irq_bypass_producer *);
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index 7006bcbc2e37..1f4896de58ca 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -124,9 +124,9 @@ void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info)
info->virt, (long)info->order, kvm->arch.lpid);
}

-long kvmppc_alloc_reset_hpt(struct kvm *kvm, int order)
+int kvmppc_alloc_reset_hpt(struct kvm *kvm, int order)
{
- long err = -EBUSY;
+ int err = -EBUSY;
struct kvm_hpt_info info;

mutex_lock(&kvm->arch.mmu_setup_lock);
@@ -1468,8 +1468,8 @@ static void resize_hpt_prepare_work(struct work_struct *work)
mutex_unlock(&kvm->arch.mmu_setup_lock);
}

-long kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
- struct kvm_ppc_resize_hpt *rhpt)
+int kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
+ struct kvm_ppc_resize_hpt *rhpt)
{
unsigned long flags = rhpt->flags;
unsigned long shift = rhpt->shift;
@@ -1534,13 +1534,13 @@ static void resize_hpt_boot_vcpu(void *opaque)
/* Nothing to do, just force a KVM exit */
}

-long kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
- struct kvm_ppc_resize_hpt *rhpt)
+int kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
+ struct kvm_ppc_resize_hpt *rhpt)
{
unsigned long flags = rhpt->flags;
unsigned long shift = rhpt->shift;
struct kvm_resize_hpt *resize;
- long ret;
+ int ret;

if (flags != 0 || kvm_is_radix(kvm))
return -EINVAL;
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 95e738ef9062..93b695b289e9 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -288,8 +288,8 @@ static const struct file_operations kvm_spapr_tce_fops = {
.release = kvm_spapr_tce_release,
};

-long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
- struct kvm_create_spapr_tce_64 *args)
+int kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
+ struct kvm_create_spapr_tce_64 *args)
{
struct kvmppc_spapr_tce_table *stt = NULL;
struct kvmppc_spapr_tce_table *siter;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 6ba68dd6190b..cd139a1edc67 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -5779,12 +5779,12 @@ static void kvmppc_irq_bypass_del_producer_hv(struct irq_bypass_consumer *cons,
}
#endif

-static long kvm_arch_vm_ioctl_hv(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+static int kvm_arch_vm_ioctl_hv(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm __maybe_unused = filp->private_data;
void __user *argp = (void __user *)arg;
- long r;
+ int r;

switch (ioctl) {

diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 9fc4dd8f66eb..5908b514bfb6 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -2042,8 +2042,8 @@ static int kvmppc_core_check_processor_compat_pr(void)
return 0;
}

-static long kvm_arch_vm_ioctl_pr(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+static int kvm_arch_vm_ioctl_pr(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
{
return -ENOTTY;
}
--
2.31.1


2023-02-03 09:44:08

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

This function only returns normal integer values, so there is
no need to declare its return value as "long".

Signed-off-by: Thomas Huth <[email protected]>
---
arch/arm64/include/asm/kvm_host.h | 4 ++--
arch/arm64/kvm/guest.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 35a159d131b5..b1a16343767f 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -963,8 +963,8 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
struct kvm_device_attr *attr);

-long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
- struct kvm_arm_copy_mte_tags *copy_tags);
+int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
+ struct kvm_arm_copy_mte_tags *copy_tags);

/* Guest/host FPSIMD coordination helpers */
int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index cf4c495a4321..80e530549c34 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -1013,8 +1013,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
return ret;
}

-long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
- struct kvm_arm_copy_mte_tags *copy_tags)
+int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
+ struct kvm_arm_copy_mte_tags *copy_tags)
{
gpa_t guest_ipa = copy_tags->guest_ipa;
size_t length = copy_tags->length;
--
2.31.1


2023-02-03 09:44:17

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 7/7] KVM: Change return type of kvm_arch_vm_ioctl() to "int"

All kvm_arch_vm_ioctl() implementations now only deal with "int"
types as return values, so we can change the return type of these
functions to use "int" instead of "long".

Signed-off-by: Thomas Huth <[email protected]>
---
arch/arm64/kvm/arm.c | 3 +--
arch/mips/kvm/mips.c | 4 ++--
arch/powerpc/kvm/powerpc.c | 5 ++---
arch/riscv/kvm/vm.c | 3 +--
arch/s390/kvm/kvm-s390.c | 3 +--
arch/x86/kvm/x86.c | 3 +--
include/linux/kvm_host.h | 3 +--
7 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 9c5573bc4614..e791ad6137b8 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1449,8 +1449,7 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
}
}

-long kvm_arch_vm_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm = filp->private_data;
void __user *argp = (void __user *)arg;
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index a25e0b73ee70..84cadaa2c2d3 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -1003,9 +1003,9 @@ void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
kvm_flush_remote_tlbs(kvm);
}

-long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
- long r;
+ int r;

switch (ioctl) {
default:
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 04494a4fb37a..6f6ba55c224f 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -2386,12 +2386,11 @@ static int kvmppc_get_cpu_char(struct kvm_ppc_cpu_char *cp)
}
#endif

-long kvm_arch_vm_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm __maybe_unused = filp->private_data;
void __user *argp = (void __user *)arg;
- long r;
+ int r;

switch (ioctl) {
case KVM_PPC_GET_PVINFO: {
diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c
index 65a964d7e70d..c13130ab459a 100644
--- a/arch/riscv/kvm/vm.c
+++ b/arch/riscv/kvm/vm.c
@@ -87,8 +87,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
return r;
}

-long kvm_arch_vm_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
return -EINVAL;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 8ad1972b8a73..86ca49814983 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -2850,8 +2850,7 @@ static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop)
return r;
}

-long kvm_arch_vm_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm = filp->private_data;
void __user *argp = (void __user *)arg;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index caa2541833dd..c03363efc774 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6653,8 +6653,7 @@ static int kvm_vm_ioctl_set_clock(struct kvm *kvm, void __user *argp)
return 0;
}

-long kvm_arch_vm_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm = filp->private_data;
void __user *argp = (void __user *)arg;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 4f26b244f6d0..ed2f1f02976b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1398,8 +1398,7 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
bool line_status);
int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
struct kvm_enable_cap *cap);
-long kvm_arch_vm_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg);
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
long kvm_arch_vm_compat_ioctl(struct file *filp, unsigned int ioctl,
unsigned long arg);

--
2.31.1


2023-02-03 09:45:26

by Thomas Huth

[permalink] [raw]
Subject: [PATCH 1/7] KVM: Standardize on "int" return types instead of "long" in kvm_main.c

KVM functions use "long" return values for functions that are wired up
to "struct file_operations", but otherwise use "int" return values for
functions that can return 0/-errno in order to avoid unintentional
divergences between 32-bit and 64-bit kernels.
Some code still uses "long" in unnecessary spots, though, which can
cause a little bit of confusion and unnecessary size casts. Let's
change these spots to use "int" types, too.

Signed-off-by: Thomas Huth <[email protected]>
---
virt/kvm/kvm_main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 9c60384b5ae0..cd46467252a9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4475,7 +4475,7 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
return 0;
}

-static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
+static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
{
switch (arg) {
case KVM_CAP_USER_MEMORY:
@@ -5053,7 +5053,7 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
static long kvm_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
- long r = -EINVAL;
+ int r = -EINVAL;

switch (ioctl) {
case KVM_GET_API_VERSION:
--
2.31.1


2023-02-03 10:17:48

by Nicholas Piggin

[permalink] [raw]
Subject: Re: [PATCH 3/7] KVM: Move KVM_GET_NR_MMU_PAGES into the deprecation section

On Fri Feb 3, 2023 at 7:42 PM AEST, Thomas Huth wrote:
> The KVM_GET_NR_MMU_PAGES ioctl is quite questionable on 64-bit hosts
> since it fails to return the full 64 bits of the value that can be
> set with the corresponding KVM_SET_NR_MMU_PAGES call. This ioctl
> likely has also never really been used by userspace applications
> (at least not by QEMU and kvmtool which I checked), so it's better
> to move it to the deprecation section in kvm.h to make it clear for
> developers that this also should not be used in new code in the
> future anymore.

Did this get included in the series inadvertently?

Thanks,
Nick

>
> Signed-off-by: Thomas Huth <[email protected]>
> ---
> include/uapi/linux/kvm.h | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 55155e262646..f55965a4cec7 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -83,6 +83,8 @@ struct kvm_debug_guest {
>
> #define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)
>
> +#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
> +
> /* *** End of deprecated interfaces *** */
>
>
> @@ -1442,7 +1444,6 @@ struct kvm_vfio_spapr_tce {
> #define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
> #define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
> #define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
> -#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
> #define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
> struct kvm_userspace_memory_region)
> #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
> --
> 2.31.1


2023-02-03 10:22:27

by Nicholas Piggin

[permalink] [raw]
Subject: Re: [PATCH 4/7] KVM: PPC: Standardize on "int" return types in the powerpc KVM code

On Fri Feb 3, 2023 at 7:42 PM AEST, Thomas Huth wrote:
> Most functions that are related to kvm_arch_vm_ioctl() already use
> "int" as return type to pass error values back to the caller. Some
> outlier functions use "long" instead for no good reason (they do not
> really require long values here). Let's standardize on "int" here to
> avoid casting the values back and forth between the two types.
>
> Signed-off-by: Thomas Huth <[email protected]>

Thanks for the patch. It looks fine to me, it should be okay to
go via Paolo's tree if he's going to take the series.

Reviewed-by: Nicholas Piggin <[email protected]>

> ---
> arch/powerpc/include/asm/kvm_ppc.h | 14 +++++++-------
> arch/powerpc/kvm/book3s_64_mmu_hv.c | 14 +++++++-------
> arch/powerpc/kvm/book3s_64_vio.c | 4 ++--
> arch/powerpc/kvm/book3s_hv.c | 6 +++---
> arch/powerpc/kvm/book3s_pr.c | 4 ++--
> 5 files changed, 21 insertions(+), 21 deletions(-)

2023-02-03 10:55:51

by Thomas Huth

[permalink] [raw]
Subject: Re: [PATCH 3/7] KVM: Move KVM_GET_NR_MMU_PAGES into the deprecation section

On 03/02/2023 11.16, Nicholas Piggin wrote:
> On Fri Feb 3, 2023 at 7:42 PM AEST, Thomas Huth wrote:
>> The KVM_GET_NR_MMU_PAGES ioctl is quite questionable on 64-bit hosts
>> since it fails to return the full 64 bits of the value that can be
>> set with the corresponding KVM_SET_NR_MMU_PAGES call. This ioctl
>> likely has also never really been used by userspace applications
>> (at least not by QEMU and kvmtool which I checked), so it's better
>> to move it to the deprecation section in kvm.h to make it clear for
>> developers that this also should not be used in new code in the
>> future anymore.
>
> Did this get included in the series inadvertently?

No, it's here on purpose, as a second step to patch 2/7 (and a follow up
from the discussion last year, see
https://lore.kernel.org/kvm/YpZu6%[email protected]/ ) ... sorry, I
should have elaborated on this in the cover letter, too.

Thomas


2023-02-07 00:10:38

by Gavin Shan

[permalink] [raw]
Subject: Re: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

Hi Thomas,

On 2/3/23 8:42 PM, Thomas Huth wrote:
> This function only returns normal integer values, so there is
> no need to declare its return value as "long".
>
> Signed-off-by: Thomas Huth <[email protected]>
> ---
> arch/arm64/include/asm/kvm_host.h | 4 ++--
> arch/arm64/kvm/guest.c | 4 ++--
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 35a159d131b5..b1a16343767f 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -963,8 +963,8 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
> int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
> struct kvm_device_attr *attr);
>
> -long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
> - struct kvm_arm_copy_mte_tags *copy_tags);
> +int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
> + struct kvm_arm_copy_mte_tags *copy_tags);
>
> /* Guest/host FPSIMD coordination helpers */
> int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index cf4c495a4321..80e530549c34 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -1013,8 +1013,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
> return ret;
> }
>
> -long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
> - struct kvm_arm_copy_mte_tags *copy_tags)
> +int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
> + struct kvm_arm_copy_mte_tags *copy_tags)
> {
> gpa_t guest_ipa = copy_tags->guest_ipa;
> size_t length = copy_tags->length;
>

It's possible for the function to return number of bytes have been copied.
Its type is 'size_t', same to 'unsigned long'. So 'int' doesn't have sufficient
space for it if I'm correct.

long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
struct kvm_arm_copy_mte_tags *copy_tags)
{
gpa_t guest_ipa = copy_tags->guest_ipa;
size_t length = copy_tags->length;
:
:
out:
mutex_unlock(&kvm->slots_lock);
/* If some data has been copied report the number of bytes copied */
if (length != copy_tags->length)
return copy_tags->length - length;
return ret;
}

Thanks,
Gavin


2023-02-07 10:11:07

by Thomas Huth

[permalink] [raw]
Subject: Re: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

On 07/02/2023 01.09, Gavin Shan wrote:
> Hi Thomas,
>
> On 2/3/23 8:42 PM, Thomas Huth wrote:
>> This function only returns normal integer values, so there is
>> no need to declare its return value as "long".
>>
>> Signed-off-by: Thomas Huth <[email protected]>
>> ---
>>   arch/arm64/include/asm/kvm_host.h | 4 ++--
>>   arch/arm64/kvm/guest.c            | 4 ++--
>>   2 files changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/kvm_host.h
>> b/arch/arm64/include/asm/kvm_host.h
>> index 35a159d131b5..b1a16343767f 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -963,8 +963,8 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
>>   int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
>>                      struct kvm_device_attr *attr);
>> -long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>> -                struct kvm_arm_copy_mte_tags *copy_tags);
>> +int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>> +                   struct kvm_arm_copy_mte_tags *copy_tags);
>>   /* Guest/host FPSIMD coordination helpers */
>>   int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
>> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
>> index cf4c495a4321..80e530549c34 100644
>> --- a/arch/arm64/kvm/guest.c
>> +++ b/arch/arm64/kvm/guest.c
>> @@ -1013,8 +1013,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
>>       return ret;
>>   }
>> -long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>> -                struct kvm_arm_copy_mte_tags *copy_tags)
>> +int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>> +                   struct kvm_arm_copy_mte_tags *copy_tags)
>>   {
>>       gpa_t guest_ipa = copy_tags->guest_ipa;
>>       size_t length = copy_tags->length;
>>
>
> It's possible for the function to return number of bytes have been copied.
> Its type is 'size_t', same to 'unsigned long'. So 'int' doesn't have sufficient
> space for it if I'm correct.
>
> long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>                                 struct kvm_arm_copy_mte_tags *copy_tags)
> {
>         gpa_t guest_ipa = copy_tags->guest_ipa;
>         size_t length = copy_tags->length;
>         :
>         :
> out:
>         mutex_unlock(&kvm->slots_lock);
>         /* If some data has been copied report the number of bytes copied */
>         if (length != copy_tags->length)
>                 return copy_tags->length - length;
>         return ret;
> }

Oh, drat, I thought I had checked all return statements ... this must have
fallen through the cracks, sorry!

Anyway, this is already a problem now: The function is called from
kvm_arch_vm_ioctl() (which still returns a long), which in turn is called
from kvm_vm_ioctl() in virt/kvm/kvm_main.c. And that functions stores the
return value in an "int r" variable. So the upper bits are already lost there.

Also, how is this supposed to work from user space? The normal "ioctl()"
libc function just returns an "int" ? Is this ioctl already used in a
userspace application somewhere? ... at least in QEMU, I didn't spot it yet...

Thomas


2023-02-07 15:36:57

by Claudio Imbrenda

[permalink] [raw]
Subject: Re: [PATCH 5/7] KVM: s390: Use "int" as return type for kvm_s390_get/set_skeys()

On Fri, 3 Feb 2023 10:42:28 +0100
Thomas Huth <[email protected]> wrote:

> These two functions only return normal integers, so it does not
> make sense to declare the return type as "long" here.
>
> Signed-off-by: Thomas Huth <[email protected]>

Reviewed-by: Claudio Imbrenda <[email protected]>

> ---
> arch/s390/kvm/kvm-s390.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index e4890e04b210..8ad1972b8a73 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -1992,7 +1992,7 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
> return ret;
> }
>
> -static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
> +static int kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
> {
> uint8_t *keys;
> uint64_t hva;
> @@ -2040,7 +2040,7 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
> return r;
> }
>
> -static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
> +static int kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
> {
> uint8_t *keys;
> uint64_t hva;


2023-02-07 22:17:45

by Gavin Shan

[permalink] [raw]
Subject: Re: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

On 2/7/23 9:09 PM, Thomas Huth wrote:
> On 07/02/2023 01.09, Gavin Shan wrote:
>> Hi Thomas,
>>
>> On 2/3/23 8:42 PM, Thomas Huth wrote:
>>> This function only returns normal integer values, so there is
>>> no need to declare its return value as "long".
>>>
>>> Signed-off-by: Thomas Huth <[email protected]>
>>> ---
>>>   arch/arm64/include/asm/kvm_host.h | 4 ++--
>>>   arch/arm64/kvm/guest.c            | 4 ++--
>>>   2 files changed, 4 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>>> index 35a159d131b5..b1a16343767f 100644
>>> --- a/arch/arm64/include/asm/kvm_host.h
>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>> @@ -963,8 +963,8 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
>>>   int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
>>>                      struct kvm_device_attr *attr);
>>> -long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>>> -                struct kvm_arm_copy_mte_tags *copy_tags);
>>> +int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>>> +                   struct kvm_arm_copy_mte_tags *copy_tags);
>>>   /* Guest/host FPSIMD coordination helpers */
>>>   int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
>>> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
>>> index cf4c495a4321..80e530549c34 100644
>>> --- a/arch/arm64/kvm/guest.c
>>> +++ b/arch/arm64/kvm/guest.c
>>> @@ -1013,8 +1013,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
>>>       return ret;
>>>   }
>>> -long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>>> -                struct kvm_arm_copy_mte_tags *copy_tags)
>>> +int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>>> +                   struct kvm_arm_copy_mte_tags *copy_tags)
>>>   {
>>>       gpa_t guest_ipa = copy_tags->guest_ipa;
>>>       size_t length = copy_tags->length;
>>>
>>
>> It's possible for the function to return number of bytes have been copied.
>> Its type is 'size_t', same to 'unsigned long'. So 'int' doesn't have sufficient
>> space for it if I'm correct.
>>
>> long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>>                                  struct kvm_arm_copy_mte_tags *copy_tags)
>> {
>>          gpa_t guest_ipa = copy_tags->guest_ipa;
>>          size_t length = copy_tags->length;
>>          :
>>          :
>> out:
>>          mutex_unlock(&kvm->slots_lock);
>>          /* If some data has been copied report the number of bytes copied */
>>          if (length != copy_tags->length)
>>                  return copy_tags->length - length;
>>          return ret;
>> }
>
> Oh, drat, I thought I had checked all return statements ... this must have fallen through the cracks, sorry!
>
> Anyway, this is already a problem now: The function is called from kvm_arch_vm_ioctl() (which still returns a long), which in turn is called from kvm_vm_ioctl() in virt/kvm/kvm_main.c. And that functions stores the return value in an "int r" variable. So the upper bits are already lost there.
>
> Also, how is this supposed to work from user space? The normal "ioctl()" libc function just returns an "int" ? Is this ioctl already used in a userspace application somewhere? ... at least in QEMU, I didn't spot it yet...
>

The ioctl command KVM_ARM_MTE_COPY_TAGS was merged recently and not used
by QEMU yet. I think struct kvm_arm_copy_mte_tags::length needs to be
'__u32' instead of '__u64' in order to standardize the return value.
Something like below. Documentation/virt/kvm/api.rst::section-4.130
needs update accordingly.

struct kvm_arm_copy_mte_tags {
__u64 guest_ipa;
__u32 pad;
__u32 length;
void __user *addr;
__u64 flags;
__u64 reserved[2];
};

Thanks,
Gavin


2023-02-08 08:50:10

by Cornelia Huck

[permalink] [raw]
Subject: Re: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

On Wed, Feb 08 2023, Gavin Shan <[email protected]> wrote:

> On 2/7/23 9:09 PM, Thomas Huth wrote:
>> Oh, drat, I thought I had checked all return statements ... this must have fallen through the cracks, sorry!
>>
>> Anyway, this is already a problem now: The function is called from kvm_arch_vm_ioctl() (which still returns a long), which in turn is called from kvm_vm_ioctl() in virt/kvm/kvm_main.c. And that functions stores the return value in an "int r" variable. So the upper bits are already lost there.
>>
>> Also, how is this supposed to work from user space? The normal "ioctl()" libc function just returns an "int" ? Is this ioctl already used in a userspace application somewhere? ... at least in QEMU, I didn't spot it yet...
>>

We will need it in QEMU to implement migration with MTE (the current
proposal simply adds a migration blocker when MTE is enabled, as there
are various other things that need to be figured out for this to work.)
But maybe other VMMs already use it (and have been lucky because they
always dealt with shorter lengths?)

>
> The ioctl command KVM_ARM_MTE_COPY_TAGS was merged recently and not used
> by QEMU yet. I think struct kvm_arm_copy_mte_tags::length needs to be
> '__u32' instead of '__u64' in order to standardize the return value.
> Something like below. Documentation/virt/kvm/api.rst::section-4.130
> needs update accordingly.
>
> struct kvm_arm_copy_mte_tags {
> __u64 guest_ipa;
> __u32 pad;
> __u32 length;
> void __user *addr;
> __u64 flags;
> __u64 reserved[2];
> };

Can we do this in a more compatible way, as we are dealing with an API?
Like returning -EINVAL if length is too big?


2023-02-08 11:51:40

by Steven Price

[permalink] [raw]
Subject: Re: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

On 08/02/2023 08:49, Cornelia Huck wrote:
> On Wed, Feb 08 2023, Gavin Shan <[email protected]> wrote:
>
>> On 2/7/23 9:09 PM, Thomas Huth wrote:
>>> Oh, drat, I thought I had checked all return statements ... this must have fallen through the cracks, sorry!
>>>
>>> Anyway, this is already a problem now: The function is called from kvm_arch_vm_ioctl() (which still returns a long), which in turn is called from kvm_vm_ioctl() in virt/kvm/kvm_main.c. And that functions stores the return value in an "int r" variable. So the upper bits are already lost there.

Sorry about that, I was caught out by kvm_arch_vm_ioctl() returning long...

>>> Also, how is this supposed to work from user space? The normal "ioctl()" libc function just returns an "int" ? Is this ioctl already used in a userspace application somewhere? ... at least in QEMU, I didn't spot it yet...
>>>
>
> We will need it in QEMU to implement migration with MTE (the current
> proposal simply adds a migration blocker when MTE is enabled, as there
> are various other things that need to be figured out for this to work.)
> But maybe other VMMs already use it (and have been lucky because they
> always dealt with shorter lengths?)
>
>>
>> The ioctl command KVM_ARM_MTE_COPY_TAGS was merged recently and not used
>> by QEMU yet. I think struct kvm_arm_copy_mte_tags::length needs to be
>> '__u32' instead of '__u64' in order to standardize the return value.
>> Something like below. Documentation/virt/kvm/api.rst::section-4.130
>> needs update accordingly.
>>
>> struct kvm_arm_copy_mte_tags {
>> __u64 guest_ipa;
>> __u32 pad;
>> __u32 length;
>> void __user *addr;
>> __u64 flags;
>> __u64 reserved[2];
>> };
>
> Can we do this in a more compatible way, as we are dealing with an API?
> Like returning -EINVAL if length is too big?
>

I agree the simplest fix for the problem is simply to reject any
lengths>INT_MAX:

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index cf4c495a4321..94aed7ce85c4 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -1032,6 +1032,13 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
if (copy_tags->flags & ~KVM_ARM_TAGS_FROM_GUEST)
return -EINVAL;

+ /*
+ * ioctl returns int, so lengths above INT_MAX cannot be
+ * represented in the return value
+ */
+ if (length > INT_MAX)
+ return -EINVAL;
+
if (length & ~PAGE_MASK || guest_ipa & ~PAGE_MASK)
return -EINVAL;

This could also be fixed in a useable way by including a new flag which
returns the length in an output field of the ioctl structure. I'm
guessing a 2GB limit would be annoying to work around.

Steve


2023-02-08 12:17:40

by Thomas Huth

[permalink] [raw]
Subject: Re: [PATCH 6/7] KVM: arm64: Change return type of kvm_vm_ioctl_mte_copy_tags() to "int"

On 08/02/2023 12.51, Steven Price wrote:
> On 08/02/2023 08:49, Cornelia Huck wrote:
>> On Wed, Feb 08 2023, Gavin Shan <[email protected]> wrote:
>>
>>> On 2/7/23 9:09 PM, Thomas Huth wrote:
>>>> Oh, drat, I thought I had checked all return statements ... this must have fallen through the cracks, sorry!
>>>>
>>>> Anyway, this is already a problem now: The function is called from kvm_arch_vm_ioctl() (which still returns a long), which in turn is called from kvm_vm_ioctl() in virt/kvm/kvm_main.c. And that functions stores the return value in an "int r" variable. So the upper bits are already lost there.
>
> Sorry about that, I was caught out by kvm_arch_vm_ioctl() returning long...

That's why I'm trying to fix that return type mess with my series, to avoid
such problems in the future :-)

>>>> Also, how is this supposed to work from user space? The normal "ioctl()" libc function just returns an "int" ? Is this ioctl already used in a userspace application somewhere? ... at least in QEMU, I didn't spot it yet...
>>>>
>>
>> We will need it in QEMU to implement migration with MTE (the current
>> proposal simply adds a migration blocker when MTE is enabled, as there
>> are various other things that need to be figured out for this to work.)
>> But maybe other VMMs already use it (and have been lucky because they
>> always dealt with shorter lengths?)
>>
>>>
>>> The ioctl command KVM_ARM_MTE_COPY_TAGS was merged recently and not used
>>> by QEMU yet. I think struct kvm_arm_copy_mte_tags::length needs to be
>>> '__u32' instead of '__u64' in order to standardize the return value.
>>> Something like below. Documentation/virt/kvm/api.rst::section-4.130
>>> needs update accordingly.
>>>
>>> struct kvm_arm_copy_mte_tags {
>>> __u64 guest_ipa;
>>> __u32 pad;
>>> __u32 length;
>>> void __user *addr;
>>> __u64 flags;
>>> __u64 reserved[2];
>>> };
>>
>> Can we do this in a more compatible way, as we are dealing with an API?
>> Like returning -EINVAL if length is too big?
>>
>
> I agree the simplest fix for the problem is simply to reject any
> lengths>INT_MAX:
>
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index cf4c495a4321..94aed7ce85c4 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -1032,6 +1032,13 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
> if (copy_tags->flags & ~KVM_ARM_TAGS_FROM_GUEST)
> return -EINVAL;
>
> + /*
> + * ioctl returns int, so lengths above INT_MAX cannot be
> + * represented in the return value
> + */
> + if (length > INT_MAX)
> + return -EINVAL;
> +
> if (length & ~PAGE_MASK || guest_ipa & ~PAGE_MASK)
> return -EINVAL;
>
> This could also be fixed in a useable way by including a new flag which
> returns the length in an output field of the ioctl structure. I'm
> guessing a 2GB limit would be annoying to work around.

I agree that checking for length > INT_MAX is likely the best thing to do
here right now. I'll add that in v2 of my series.

But actually, this might even be a good thing from another point of view (so
I'm not sure whether your idea with the flag should really be pursued): The
code here takes a mutex and then runs a while loop that depends on the
length - which could cause the lock to be held for a rather long time if
length is a 64-bit value. Forcing the user space to limit the length here
could help to avoid taking the lock for too long.

Thomas


2023-02-08 17:41:31

by Claudio Imbrenda

[permalink] [raw]
Subject: Re: [PATCH 7/7] KVM: Change return type of kvm_arch_vm_ioctl() to "int"

On Fri, 3 Feb 2023 10:42:30 +0100
Thomas Huth <[email protected]> wrote:

> All kvm_arch_vm_ioctl() implementations now only deal with "int"
> types as return values, so we can change the return type of these
> functions to use "int" instead of "long".
>
> Signed-off-by: Thomas Huth <[email protected]>

Acked-by: Claudio Imbrenda <[email protected]>

> ---
> arch/arm64/kvm/arm.c | 3 +--
> arch/mips/kvm/mips.c | 4 ++--
> arch/powerpc/kvm/powerpc.c | 5 ++---
> arch/riscv/kvm/vm.c | 3 +--
> arch/s390/kvm/kvm-s390.c | 3 +--
> arch/x86/kvm/x86.c | 3 +--
> include/linux/kvm_host.h | 3 +--
> 7 files changed, 9 insertions(+), 15 deletions(-)
>
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 9c5573bc4614..e791ad6137b8 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -1449,8 +1449,7 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
> }
> }
>
> -long kvm_arch_vm_ioctl(struct file *filp,
> - unsigned int ioctl, unsigned long arg)
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> {
> struct kvm *kvm = filp->private_data;
> void __user *argp = (void __user *)arg;
> diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> index a25e0b73ee70..84cadaa2c2d3 100644
> --- a/arch/mips/kvm/mips.c
> +++ b/arch/mips/kvm/mips.c
> @@ -1003,9 +1003,9 @@ void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
> kvm_flush_remote_tlbs(kvm);
> }
>
> -long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> {
> - long r;
> + int r;
>
> switch (ioctl) {
> default:
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 04494a4fb37a..6f6ba55c224f 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -2386,12 +2386,11 @@ static int kvmppc_get_cpu_char(struct kvm_ppc_cpu_char *cp)
> }
> #endif
>
> -long kvm_arch_vm_ioctl(struct file *filp,
> - unsigned int ioctl, unsigned long arg)
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> {
> struct kvm *kvm __maybe_unused = filp->private_data;
> void __user *argp = (void __user *)arg;
> - long r;
> + int r;
>
> switch (ioctl) {
> case KVM_PPC_GET_PVINFO: {
> diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c
> index 65a964d7e70d..c13130ab459a 100644
> --- a/arch/riscv/kvm/vm.c
> +++ b/arch/riscv/kvm/vm.c
> @@ -87,8 +87,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> return r;
> }
>
> -long kvm_arch_vm_ioctl(struct file *filp,
> - unsigned int ioctl, unsigned long arg)
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> {
> return -EINVAL;
> }
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 8ad1972b8a73..86ca49814983 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -2850,8 +2850,7 @@ static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop)
> return r;
> }
>
> -long kvm_arch_vm_ioctl(struct file *filp,
> - unsigned int ioctl, unsigned long arg)
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> {
> struct kvm *kvm = filp->private_data;
> void __user *argp = (void __user *)arg;
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index caa2541833dd..c03363efc774 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -6653,8 +6653,7 @@ static int kvm_vm_ioctl_set_clock(struct kvm *kvm, void __user *argp)
> return 0;
> }
>
> -long kvm_arch_vm_ioctl(struct file *filp,
> - unsigned int ioctl, unsigned long arg)
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> {
> struct kvm *kvm = filp->private_data;
> void __user *argp = (void __user *)arg;
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 4f26b244f6d0..ed2f1f02976b 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1398,8 +1398,7 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
> bool line_status);
> int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
> struct kvm_enable_cap *cap);
> -long kvm_arch_vm_ioctl(struct file *filp,
> - unsigned int ioctl, unsigned long arg);
> +int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg);
> long kvm_arch_vm_compat_ioctl(struct file *filp, unsigned int ioctl,
> unsigned long arg);
>