mlx4_init_user_cqes() fills a scratch buffer with the CQE
initialization pattern and then copies from that buffer to userspace.
In the single-copy path, the copy length is array_size(entries,
cqe_size), but the scratch buffer is allocated with PAGE_SIZE. GCC 10
does not carry the branch invariant strongly enough through the object
size checks and falsely triggers __bad_copy_from().
Size the scratch buffer to the actual copy length for the active path,
keep array_size() for the single-copy case, and retain a WARN_ON_ONCE()
guard for the PAGE_SIZE invariant before allocating the buffer.
Fixes: f69bf5dee7ef ("net/mlx4: Use array_size() helper in copy_to_user()")
Signed-off-by: Yao Sang <sangyao@kylinos.cn>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
{
int entries_per_copy = PAGE_SIZE / cqe_size;
+ size_t copy_bytes;
void *init_ents;
int err = 0;
int i;
buf += PAGE_SIZE;
}
} else {
+ copy_bytes = array_size(entries, cqe_size);
+ if (WARN_ON_ONCE(copy_bytes > PAGE_SIZE)) {
+ err = -EINVAL;
+ goto out;
+ }
+
err = copy_to_user((void __user *)buf, init_ents,
- array_size(entries, cqe_size)) ?
+ copy_bytes) ?
-EFAULT : 0;
}