Instead of silently truncating extended QUERY_DEVICE uverb's
response, see commit 5a77abf9a97a ("IB/core: Add support for
extended query device caps")), this patch makes function
ib_uverbs_ex_query_device() check the available space in the
response buffer against the requested features set in comp_mask
(currently only IB_USER_VERBS_EX_QUERY_DEVICE_ODP per commit
860f10a799c8 ("IB/core: Add flags for on demand paging support").

If the response buffer is not large enough to store the expected
response, -ENOSPC is returned to userspace so that it can adjust
the size of its buffer.

Note: as offsetof() is used to retrieve the size of the lower chunk
of the response, beware that it only works if the upper chunk
is right after, without any implicit padding. And, as the size of
the latter chunk is added to the base size, implicit padding at the
end of the structure is not taken in account. Both point must be
taken in account when extending the uverbs functionalities.

Link: http://mid.gmane.org/[email protected]
Cc: Sagi Grimberg <[email protected]>
Cc: Shachar Raindel <[email protected]>
Cc: Eli Cohen <[email protected]>
Cc: Haggai Eran <[email protected]>
Signed-off-by: Yann Droneaud <[email protected]>
---
 drivers/infiniband/core/uverbs_cmd.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/core/uverbs_cmd.c 
b/drivers/infiniband/core/uverbs_cmd.c
index 532d8eba8b02..8668b328b7e6 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -3302,6 +3302,7 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
        struct ib_uverbs_ex_query_device  cmd;
        struct ib_device_attr attr;
        struct ib_device *device;
+       size_t resp_len;
        int err;
 
        device = file->device->ib_dev;
@@ -3315,6 +3316,11 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file 
*file,
        if (cmd.reserved)
                return -EINVAL;
 
+       resp_len = offsetof(typeof(resp), odp_caps);
+
+       if (ucore->outlen < resp_len)
+               return -ENOSPC;
+
        err = device->query_device(device, &attr);
        if (err)
                return err;
@@ -3325,6 +3331,11 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file 
*file,
 
 #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
        if (cmd.comp_mask & IB_USER_VERBS_EX_QUERY_DEVICE_ODP) {
+               resp_len += sizeof(resp.odp_caps);
+
+               if (ucore->outlen < resp_len)
+                       return -ENOSPC;
+
                resp.odp_caps.general_caps = attr.odp_caps.general_caps;
                resp.odp_caps.per_transport_caps.rc_odp_caps =
                        attr.odp_caps.per_transport_caps.rc_odp_caps;
@@ -3336,7 +3347,7 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
        }
 #endif
 
-       err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+       err = ib_copy_to_udata(ucore, &resp, resp_len);
        if (err)
                return err;
 
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to