RDMA: Directly cast the sockaddr union to sockaddr [Linux 4.9.189]

This Linux kernel change "RDMA: Directly cast the sockaddr union to sockaddr" is included in the Linux 4.9.189 release. This change is authored by Jason Gunthorpe <jgg [at] mellanox.com> on Sun May 12 21:57:57 2019 -0300. The commit for this change in Linux stable tree is 7d5750c (patch) which is from upstream commit 641114d. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 641114d.

RDMA: Directly cast the sockaddr union to sockaddr

commit 641114d2af312d39ca9bbc2369d18a5823da51c6 upstream.

gcc 9 now does allocation size tracking and thinks that passing the member
of a union and then accessing beyond that member's bounds is an overflow.

Instead of using the union member, use the entire union with a cast to
get to the sockaddr. gcc will now know that the memory extends the full
size of the union.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 25 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/infiniband/core/addr.c           | 15 +++++++--------
 drivers/infiniband/hw/ocrdma/ocrdma_ah.c |  5 ++---
 drivers/infiniband/hw/ocrdma/ocrdma_hw.c |  5 ++---
 3 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 978b8d9..1baa25e 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -735,14 +735,13 @@ int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
    struct net_device *dev;

    union {
-       struct sockaddr     _sockaddr;
        struct sockaddr_in  _sockaddr_in;
        struct sockaddr_in6 _sockaddr_in6;
    } sgid_addr, dgid_addr;

-   rdma_gid2ip(&sgid_addr._sockaddr, sgid);
-   rdma_gid2ip(&dgid_addr._sockaddr, dgid);
+   rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
+   rdma_gid2ip((struct sockaddr *)&dgid_addr, dgid);

    memset(&dev_addr, 0, sizeof(dev_addr));
    if (if_index)
@@ -751,8 +750,9 @@ int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,

    ctx.addr = &dev_addr;
    init_completion(&ctx.comp);
-   ret = rdma_resolve_ip(&self, &sgid_addr._sockaddr, &dgid_addr._sockaddr,
-           &dev_addr, 1000, resolve_cb, &ctx);
+   ret = rdma_resolve_ip(&self, (struct sockaddr *)&sgid_addr,
+                 (struct sockaddr *)&dgid_addr, &dev_addr, 1000,
+                 resolve_cb, &ctx);
    if (ret)
        return ret;

@@ -782,16 +782,15 @@ int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
    int ret = 0;
    struct rdma_dev_addr dev_addr;
    union {
-       struct sockaddr     _sockaddr;
        struct sockaddr_in  _sockaddr_in;
        struct sockaddr_in6 _sockaddr_in6;
    } gid_addr;

-   rdma_gid2ip(&gid_addr._sockaddr, sgid);
+   rdma_gid2ip((struct sockaddr *)&gid_addr, sgid);

    memset(&dev_addr, 0, sizeof(dev_addr));
    dev_addr.net = &init_net;
-   ret = rdma_translate_ip(&gid_addr._sockaddr, &dev_addr, vlan_id);
+   ret = rdma_translate_ip((struct sockaddr *)&gid_addr, &dev_addr, vlan_id);
    if (ret)
        return ret;

diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index 797362a..35efd40 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -82,7 +82,6 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
    u8 nxthdr = 0x11;
    struct iphdr ipv4;
    union {
-       struct sockaddr     _sockaddr;
        struct sockaddr_in  _sockaddr_in;
        struct sockaddr_in6 _sockaddr_in6;
    } sgid_addr, dgid_addr;
@@ -131,9 +130,9 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
        ipv4.tot_len = htons(0);
        ipv4.ttl = attr->grh.hop_limit;
        ipv4.protocol = nxthdr;
-       rdma_gid2ip(&sgid_addr._sockaddr, sgid);
+       rdma_gid2ip((struct sockaddr *)&sgid_addr, sgid);
        ipv4.saddr = sgid_addr._sockaddr_in.sin_addr.s_addr;
-       rdma_gid2ip(&dgid_addr._sockaddr, &attr->grh.dgid);
+       rdma_gid2ip((struct sockaddr *)&dgid_addr, &attr->grh.dgid);
        ipv4.daddr = dgid_addr._sockaddr_in.sin_addr.s_addr;
        memcpy((u8 *)ah->av + eth_sz, &ipv4, sizeof(struct iphdr));
    } else {
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 67fc0b6..edfa228 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -2505,7 +2505,6 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
    u32 vlan_id = 0xFFFF;
    u8 mac_addr[6], hdr_type;
    union {
-       struct sockaddr     _sockaddr;
        struct sockaddr_in  _sockaddr_in;
        struct sockaddr_in6 _sockaddr_in6;
    } sgid_addr, dgid_addr;
@@ -2550,8 +2549,8 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,

    hdr_type = ib_gid_to_network_type(sgid_attr.gid_type, &sgid);
    if (hdr_type == RDMA_NETWORK_IPV4) {
-       rdma_gid2ip(&sgid_addr._sockaddr, &sgid);
-       rdma_gid2ip(&dgid_addr._sockaddr, &ah_attr->grh.dgid);
+       rdma_gid2ip((struct sockaddr *)&sgid_addr, &sgid);
+       rdma_gid2ip((struct sockaddr *)&dgid_addr, &ah_attr->grh.dgid);
        memcpy(&cmd->params.dgid[0],
               &dgid_addr._sockaddr_in.sin_addr.s_addr, 4);
        memcpy(&cmd->params.sgid[0],

Leave a Reply

Your email address will not be published. Required fields are marked *