diff options
author | Yann Droneaud <ydroneaud@opteya.com> | 2014-05-05 13:33:22 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-05-27 14:53:16 -0400 |
commit | 43bc889380c2ad9aa230eccc03a15cc52cf710d4 (patch) | |
tree | f435c4c7a947a84a9c711840322910e607ea2149 | |
parent | a8237b32a3faab155a5dc8f886452147ce73da3e (diff) |
IB/mlx5: add missing padding at end of struct mlx5_ib_create_srq
The i386 ABI disagrees with most other ABIs regarding alignment of
data type larger than 4 bytes: on most ABIs a padding must be added at
end of the structures, while it is not required on i386.
So for most ABIs struct mlx5_ib_create_srq gets implicitly padded to be
aligned on a 8 bytes multiple, while for i386, such padding is not
added.
Tool pahole could be used to find such implicit padding:
$ pahole --anon_include \
--nested_anon_include \
--recursive \
--class_name mlx5_ib_create_srq \
drivers/infiniband/hw/mlx5/mlx5_ib.o
Then, structure layout can be compared between i386 and x86_64:
+++ obj-i386/drivers/infiniband/hw/mlx5/mlx5_ib.o.pahole.txt 2014-03-28 11:43:07.386413682 +0100
--- obj-x86_64/drivers/infiniband/hw/mlx5/mlx5_ib.o.pahole.txt 2014-03-27 13:06:17.788472721 +0100
@@ -69,7 +68,6 @@ struct mlx5_ib_create_srq {
__u64 db_addr; /* 8 8 */
__u32 flags; /* 16 4 */
- /* size: 20, cachelines: 1, members: 3 */
- /* last cacheline: 20 bytes */
+ /* size: 24, cachelines: 1, members: 3 */
+ /* padding: 4 */
+ /* last cacheline: 24 bytes */
};
ABI disagreement will make an x86_64 kernel try to read past
the buffer provided by an i386 binary.
When boundary check will be implemented, the x86_64 kernel will
refuse to read past the i386 userspace provided buffer and the
uverb will fail.
Anyway, if the structure lay in memory on a page boundary and
next page is not mapped, ib_copy_from_udata() will fail and the
uverb will fail.
This patch makes create_srq_user() takes care of the input
data size to handle the case where no padding was provided.
This way, x86_64 kernel will be able to handle struct mlx5_ib_create_srq
as sent by unpatched and patched i386 libmlx5.
Link: http://marc.info/?i=cover.1399309513.git.ydroneaud@opteya.com
Cc: <stable@vger.kernel.org>
Fixes: e126ba97dba9e ("mlx5: Add driver for Mellanox Connect-IB adapter")
Signed-off-by: Yann Droneaud <ydroneaud@opteya.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/hw/mlx5/srq.c | 14 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/user.h | 1 |
2 files changed, 14 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 210b3eaf188a..384af6dec5eb 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/mlx5/srq.h> | 35 | #include <linux/mlx5/srq.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <rdma/ib_umem.h> | 37 | #include <rdma/ib_umem.h> |
38 | #include <rdma/ib_user_verbs.h> | ||
38 | 39 | ||
39 | #include "mlx5_ib.h" | 40 | #include "mlx5_ib.h" |
40 | #include "user.h" | 41 | #include "user.h" |
@@ -78,16 +79,27 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, | |||
78 | { | 79 | { |
79 | struct mlx5_ib_dev *dev = to_mdev(pd->device); | 80 | struct mlx5_ib_dev *dev = to_mdev(pd->device); |
80 | struct mlx5_ib_create_srq ucmd; | 81 | struct mlx5_ib_create_srq ucmd; |
82 | size_t ucmdlen; | ||
81 | int err; | 83 | int err; |
82 | int npages; | 84 | int npages; |
83 | int page_shift; | 85 | int page_shift; |
84 | int ncont; | 86 | int ncont; |
85 | u32 offset; | 87 | u32 offset; |
86 | 88 | ||
87 | if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) { | 89 | ucmdlen = |
90 | (udata->inlen - sizeof(struct ib_uverbs_cmd_hdr) < | ||
91 | sizeof(ucmd)) ? (sizeof(ucmd) - | ||
92 | sizeof(ucmd.reserved)) : sizeof(ucmd); | ||
93 | |||
94 | if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) { | ||
88 | mlx5_ib_dbg(dev, "failed copy udata\n"); | 95 | mlx5_ib_dbg(dev, "failed copy udata\n"); |
89 | return -EFAULT; | 96 | return -EFAULT; |
90 | } | 97 | } |
98 | |||
99 | if (ucmdlen == sizeof(ucmd) && | ||
100 | ucmd.reserved != 0) | ||
101 | return -EINVAL; | ||
102 | |||
91 | srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE); | 103 | srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE); |
92 | 104 | ||
93 | srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, buf_size, | 105 | srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, buf_size, |
diff --git a/drivers/infiniband/hw/mlx5/user.h b/drivers/infiniband/hw/mlx5/user.h index d44ecd2c2faf..d0ba264ac1ed 100644 --- a/drivers/infiniband/hw/mlx5/user.h +++ b/drivers/infiniband/hw/mlx5/user.h | |||
@@ -110,6 +110,7 @@ struct mlx5_ib_create_srq { | |||
110 | __u64 buf_addr; | 110 | __u64 buf_addr; |
111 | __u64 db_addr; | 111 | __u64 db_addr; |
112 | __u32 flags; | 112 | __u32 flags; |
113 | __u32 reserved; /* explicit padding (optional on i386) */ | ||
113 | }; | 114 | }; |
114 | 115 | ||
115 | struct mlx5_ib_create_srq_resp { | 116 | struct mlx5_ib_create_srq_resp { |