]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/mlx4: avoid GCC 10 __bad_copy_from() false positive
authorYao Sang <sangyao@kylinos.cn>
Wed, 3 Jun 2026 06:10:44 +0000 (14:10 +0800)
committerJakub Kicinski <kuba@kernel.org>
Tue, 9 Jun 2026 00:22:24 +0000 (17:22 -0700)
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>
drivers/net/ethernet/mellanox/mlx4/cq.c

index e130e7259275a382ddfd005bc3f880a9d75a7ced..5c55971abbf072a7a9ab81303b9515ae6a8bbce8 100644 (file)
@@ -290,6 +290,7 @@ static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 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;
@@ -314,8 +315,14 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
                        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;
        }