RDMA/uverbs: Fix incorrect variable type
authorAvihai Horon <avihaih@nvidia.com>
Tue, 8 Dec 2020 07:35:45 +0000 (09:35 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Dec 2020 10:53:47 +0000 (11:53 +0100)
[ Upstream commit e0da68994d16b46384cce7b86eb645f1ef7c51ef ]

Fix incorrect type of max_entries in UVERBS_METHOD_QUERY_GID_TABLE -
max_entries is of type size_t although it can take negative values.

The following static check revealed it:

drivers/infiniband/core/uverbs_std_types_device.c:338 ib_uverbs_handler_UVERBS_METHOD_QUERY_GID_TABLE() warn: 'max_entries' unsigned <= 0

Fixes: 9f85cbe50aa0 ("RDMA/uverbs: Expose the new GID query API to user space")
Link: https://lore.kernel.org/r/20201208073545.9723-4-leon@kernel.org
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/infiniband/core/uverbs_std_types_device.c
include/rdma/uverbs_ioctl.h

index 302f898..9ec6971 100644 (file)
@@ -317,8 +317,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(
        struct ib_device *ib_dev;
        size_t user_entry_size;
        ssize_t num_entries;
-       size_t max_entries;
-       size_t num_bytes;
+       int max_entries;
        u32 flags;
        int ret;
 
@@ -336,19 +335,16 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(
                attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
                user_entry_size);
        if (max_entries <= 0)
-               return -EINVAL;
+               return max_entries ?: -EINVAL;
 
        ucontext = ib_uverbs_get_ucontext(attrs);
        if (IS_ERR(ucontext))
                return PTR_ERR(ucontext);
        ib_dev = ucontext->device;
 
-       if (check_mul_overflow(max_entries, sizeof(*entries), &num_bytes))
-               return -EINVAL;
-
-       entries = uverbs_zalloc(attrs, num_bytes);
-       if (!entries)
-               return -ENOMEM;
+       entries = uverbs_kcalloc(attrs, max_entries, sizeof(*entries));
+       if (IS_ERR(entries))
+               return PTR_ERR(entries);
 
        num_entries = rdma_query_gid_table(ib_dev, entries, max_entries);
        if (num_entries < 0)
index b00270c..94fac55 100644 (file)
@@ -862,6 +862,16 @@ static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
 {
        return _uverbs_alloc(bundle, size, GFP_KERNEL | __GFP_ZERO);
 }
+
+static inline __malloc void *uverbs_kcalloc(struct uverbs_attr_bundle *bundle,
+                                           size_t n, size_t size)
+{
+       size_t bytes;
+
+       if (unlikely(check_mul_overflow(n, size, &bytes)))
+               return ERR_PTR(-EOVERFLOW);
+       return uverbs_zalloc(bundle, bytes);
+}
 int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
                      size_t idx, s64 lower_bound, u64 upper_bound,
                      s64 *def_val);