diff options
author | Yann Droneaud <ydroneaud@opteya.com> | 2014-05-05 13:33:23 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-05-30 00:44:57 -0400 |
commit | b6f04d3d21458818073a2f5af5339f958864bf71 (patch) | |
tree | 15c9164e83d39d79337d1e904095e9ab91ceb963 /drivers/infiniband/hw/cxgb4 | |
parent | 11b8e22d4d0979d8201cbdf0b5fffdbe2d5bcedf (diff) |
RDMA/cxgb4: Add missing padding at end of struct c4iw_create_cq_resp
The i386 ABI disagrees with most other ABIs regarding alignment of
data types 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 ABI struct c4iw_create_cq_resp gets implicitly padded
to be aligned on a 8 bytes multiple, while for i386, such padding
is not added.
The tool pahole can be used to find such implicit padding:
$ pahole --anon_include \
--nested_anon_include \
--recursive \
--class_name c4iw_create_cq_resp \
drivers/infiniband/hw/cxgb4/iw_cxgb4.o
Then, structure layout can be compared between i386 and x86_64:
+++ obj-i386/drivers/infiniband/hw/cxgb4/iw_cxgb4.o.pahole.txt 2014-03-28 11:43:05.547432195 +0100
--- obj-x86_64/drivers/infiniband/hw/cxgb4/iw_cxgb4.o.pahole.txt 2014-03-28 10:55:10.990133017 +0100
@@ -14,9 +13,8 @@ struct c4iw_create_cq_resp {
__u32 size; /* 28 4 */
__u32 qid_mask; /* 32 4 */
- /* size: 36, cachelines: 1, members: 6 */
- /* last cacheline: 36 bytes */
+ /* size: 40, cachelines: 1, members: 6 */
+ /* padding: 4 */
+ /* last cacheline: 40 bytes */
};
This ABI disagreement will make an x86_64 kernel try to write past the
buffer provided by an i386 binary.
When boundary check will be implemented, the x86_64 kernel will refuse
to write past the i386 userspace provided buffer and the uverbs will
fail.
If the structure is on a page boundary and the next page is not
mapped, ib_copy_to_udata() will fail and the uverb will fail.
This patch adds an explicit padding at end of structure
c4iw_create_cq_resp, and, like 92b0ca7cb149 ("IB/mlx5: Fix stack info
leak in mlx5_ib_alloc_ucontext()"), makes function c4iw_create_cq()
not writting this padding field to userspace. This way, x86_64 kernel
will be able to write struct c4iw_create_cq_resp as expected by
unpatched and patched i386 libcxgb4.
Link: http://marc.info/?i=cover.1399309513.git.ydroneaud@opteya.com
Cc: <stable@vger.kernel.org>
Fixes: cfdda9d764362 ("RDMA/cxgb4: Add driver for Chelsio T4 RNIC")
Fixes: e24a72a3302a6 ("RDMA/cxgb4: Fix four byte info leak in c4iw_create_cq()")
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Yann Droneaud <ydroneaud@opteya.com>
Acked-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4')
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cq.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/user.h | 1 |
2 files changed, 3 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index cfaa56ada189..7151a02b4ebb 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c | |||
@@ -940,7 +940,6 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, | |||
940 | if (!mm2) | 940 | if (!mm2) |
941 | goto err4; | 941 | goto err4; |
942 | 942 | ||
943 | memset(&uresp, 0, sizeof(uresp)); | ||
944 | uresp.qid_mask = rhp->rdev.cqmask; | 943 | uresp.qid_mask = rhp->rdev.cqmask; |
945 | uresp.cqid = chp->cq.cqid; | 944 | uresp.cqid = chp->cq.cqid; |
946 | uresp.size = chp->cq.size; | 945 | uresp.size = chp->cq.size; |
@@ -951,7 +950,8 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, | |||
951 | uresp.gts_key = ucontext->key; | 950 | uresp.gts_key = ucontext->key; |
952 | ucontext->key += PAGE_SIZE; | 951 | ucontext->key += PAGE_SIZE; |
953 | spin_unlock(&ucontext->mmap_lock); | 952 | spin_unlock(&ucontext->mmap_lock); |
954 | ret = ib_copy_to_udata(udata, &uresp, sizeof uresp); | 953 | ret = ib_copy_to_udata(udata, &uresp, |
954 | sizeof(uresp) - sizeof(uresp.reserved)); | ||
955 | if (ret) | 955 | if (ret) |
956 | goto err5; | 956 | goto err5; |
957 | 957 | ||
diff --git a/drivers/infiniband/hw/cxgb4/user.h b/drivers/infiniband/hw/cxgb4/user.h index 11ccd276e5d9..9b7534b5f07d 100644 --- a/drivers/infiniband/hw/cxgb4/user.h +++ b/drivers/infiniband/hw/cxgb4/user.h | |||
@@ -48,6 +48,7 @@ struct c4iw_create_cq_resp { | |||
48 | __u32 cqid; | 48 | __u32 cqid; |
49 | __u32 size; | 49 | __u32 size; |
50 | __u32 qid_mask; | 50 | __u32 qid_mask; |
51 | __u32 reserved; /* explicit padding (optional for i386) */ | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | 54 | ||