e1c05b3bf8
A hwprobe pair key is signed, but the hwprobe vDSO function was
only checking that the upper bound was valid. In order to help
avoid this type of problem in the future, and in anticipation of
this check becoming more complicated with sparse keys, introduce
and use a "key is valid" predicate function for the check.
Fixes: aa5af0aa90
("RISC-V: Add hwprobe vDSO function and data")
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Evan Green <evan@rivosinc.com>
Link: https://lore.kernel.org/r/20231010165101.14942-2-ajones@ventanamicro.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
53 lines
1.4 KiB
C
53 lines
1.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright 2023 Rivos, Inc
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <vdso/datapage.h>
|
|
#include <vdso/helpers.h>
|
|
|
|
extern int riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
|
|
size_t cpu_count, unsigned long *cpus,
|
|
unsigned int flags);
|
|
|
|
/* Add a prototype to avoid -Wmissing-prototypes warning. */
|
|
int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
|
|
size_t cpu_count, unsigned long *cpus,
|
|
unsigned int flags);
|
|
|
|
int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
|
|
size_t cpu_count, unsigned long *cpus,
|
|
unsigned int flags)
|
|
{
|
|
const struct vdso_data *vd = __arch_get_vdso_data();
|
|
const struct arch_vdso_data *avd = &vd->arch_data;
|
|
bool all_cpus = !cpu_count && !cpus;
|
|
struct riscv_hwprobe *p = pairs;
|
|
struct riscv_hwprobe *end = pairs + pair_count;
|
|
|
|
/*
|
|
* Defer to the syscall for exotic requests. The vdso has answers
|
|
* stashed away only for the "all cpus" case. If all CPUs are
|
|
* homogeneous, then this function can handle requests for arbitrary
|
|
* masks.
|
|
*/
|
|
if ((flags != 0) || (!all_cpus && !avd->homogeneous_cpus))
|
|
return riscv_hwprobe(pairs, pair_count, cpu_count, cpus, flags);
|
|
|
|
/* This is something we can handle, fill out the pairs. */
|
|
while (p < end) {
|
|
if (riscv_hwprobe_key_is_valid(p->key)) {
|
|
p->value = avd->all_cpu_hwprobe_values[p->key];
|
|
|
|
} else {
|
|
p->key = -1;
|
|
p->value = 0;
|
|
}
|
|
|
|
p++;
|
|
}
|
|
|
|
return 0;
|
|
}
|