Skip to content

Commit 67325e9

Browse files
committed
KVM: PPC: Book3S PR: Check copy_to/from_user return values
The PR KVM implementation of the PAPR HPT hypercalls (H_ENTER etc.) access an image of the HPT in userspace memory using copy_from_user and copy_to_user. Recently, the declarations of those functions were annotated to indicate that the return value must be checked. Since this code doesn't currently check the return value, this causes compile warnings like the ones shown below, and since on PPC the default is to compile arch/powerpc with -Werror, this causes the build to fail. To fix this, we check the return values, and if non-zero, fail the hypercall being processed with a H_FUNCTION error return value. There is really no good error return value to use since PAPR didn't envisage the possibility that the hypervisor may not be able to access the guest's HPT, and H_FUNCTION (function not supported) seems as good as any. The typical compile warnings look like this: CC arch/powerpc/kvm/book3s_pr_papr.o /home/paulus/kernel/kvm/arch/powerpc/kvm/book3s_pr_papr.c: In function ‘kvmppc_h_pr_enter’: /home/paulus/kernel/kvm/arch/powerpc/kvm/book3s_pr_papr.c:53:2: error: ignoring return value of ‘copy_from_user’, declared with attribute warn_unused_result [-Werror=unused-result] copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)); ^ /home/paulus/kernel/kvm/arch/powerpc/kvm/book3s_pr_papr.c:74:2: error: ignoring return value of ‘copy_to_user’, declared with attribute warn_unused_result [-Werror=unused-result] copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE); ^ ... etc. Signed-off-by: Paul Mackerras <[email protected]>
1 parent acde257 commit 67325e9

File tree

1 file changed

+26
-8
lines changed

1 file changed

+26
-8
lines changed

arch/powerpc/kvm/book3s_pr_papr.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
5050
pteg_addr = get_pteg_addr(vcpu, pte_index);
5151

5252
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
53-
copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
53+
ret = H_FUNCTION;
54+
if (copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)))
55+
goto done;
5456
hpte = pteg;
5557

5658
ret = H_PTEG_FULL;
@@ -71,7 +73,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
7173
hpte[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
7274
hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
7375
pteg_addr += i * HPTE_SIZE;
74-
copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE);
76+
ret = H_FUNCTION;
77+
if (copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE))
78+
goto done;
7579
kvmppc_set_gpr(vcpu, 4, pte_index | i);
7680
ret = H_SUCCESS;
7781

@@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
9397

9498
pteg = get_pteg_addr(vcpu, pte_index);
9599
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
96-
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
100+
ret = H_FUNCTION;
101+
if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
102+
goto done;
97103
pte[0] = be64_to_cpu((__force __be64)pte[0]);
98104
pte[1] = be64_to_cpu((__force __be64)pte[1]);
99105

@@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
103109
((flags & H_ANDCOND) && (pte[0] & avpn) != 0))
104110
goto done;
105111

106-
copy_to_user((void __user *)pteg, &v, sizeof(v));
112+
ret = H_FUNCTION;
113+
if (copy_to_user((void __user *)pteg, &v, sizeof(v)))
114+
goto done;
107115

108116
rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
109117
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
@@ -171,7 +179,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
171179
}
172180

173181
pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
174-
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
182+
if (copy_from_user(pte, (void __user *)pteg, sizeof(pte))) {
183+
ret = H_FUNCTION;
184+
break;
185+
}
175186
pte[0] = be64_to_cpu((__force __be64)pte[0]);
176187
pte[1] = be64_to_cpu((__force __be64)pte[1]);
177188

@@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
184195
tsh |= H_BULK_REMOVE_NOT_FOUND;
185196
} else {
186197
/* Splat the pteg in (userland) hpt */
187-
copy_to_user((void __user *)pteg, &v, sizeof(v));
198+
if (copy_to_user((void __user *)pteg, &v, sizeof(v))) {
199+
ret = H_FUNCTION;
200+
break;
201+
}
188202

189203
rb = compute_tlbie_rb(pte[0], pte[1],
190204
tsh & H_BULK_REMOVE_PTEX);
@@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
211225

212226
pteg = get_pteg_addr(vcpu, pte_index);
213227
mutex_lock(&vcpu->kvm->arch.hpt_mutex);
214-
copy_from_user(pte, (void __user *)pteg, sizeof(pte));
228+
ret = H_FUNCTION;
229+
if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
230+
goto done;
215231
pte[0] = be64_to_cpu((__force __be64)pte[0]);
216232
pte[1] = be64_to_cpu((__force __be64)pte[1]);
217233

@@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
234250
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
235251
pte[0] = (__force u64)cpu_to_be64(pte[0]);
236252
pte[1] = (__force u64)cpu_to_be64(pte[1]);
237-
copy_to_user((void __user *)pteg, pte, sizeof(pte));
253+
ret = H_FUNCTION;
254+
if (copy_to_user((void __user *)pteg, pte, sizeof(pte)))
255+
goto done;
238256
ret = H_SUCCESS;
239257

240258
done:

0 commit comments

Comments
 (0)