| From foo@baz Mon Dec 18 13:29:00 CET 2017 |
| From: Bart Van Assche <bart.vanassche@wdc.com> |
| Date: Wed, 11 Oct 2017 10:48:45 -0700 |
| Subject: RDMA/cma: Avoid triggering undefined behavior |
| |
| From: Bart Van Assche <bart.vanassche@wdc.com> |
| |
| |
| [ Upstream commit c0b64f58e8d49570aa9ee55d880f92c20ff0166b ] |
| |
| According to the C standard the behavior of computations with |
| integer operands is as follows: |
| * A computation involving unsigned operands can never overflow, |
| because a result that cannot be represented by the resulting |
| unsigned integer type is reduced modulo the number that is one |
| greater than the largest value that can be represented by the |
| resulting type. |
| * The behavior for signed integer underflow and overflow is |
| undefined. |
| |
| Hence only use unsigned integers when checking for integer |
| overflow. |
| |
| This patch is what I came up with after having analyzed the |
| following smatch warnings: |
| |
| drivers/infiniband/core/cma.c:3448: cma_resolve_ib_udp() warn: signed overflow undefined. 'offset + conn_param->private_data_len < conn_param->private_data_len' |
| drivers/infiniband/core/cma.c:3505: cma_connect_ib() warn: signed overflow undefined. 'offset + conn_param->private_data_len < conn_param->private_data_len' |
| |
| Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> |
| Acked-by: Sean Hefty <sean.hefty@intel.com> |
| Signed-off-by: Doug Ledford <dledford@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/infiniband/core/cma.c | 11 +++++++---- |
| 1 file changed, 7 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/infiniband/core/cma.c |
| +++ b/drivers/infiniband/core/cma.c |
| @@ -1540,7 +1540,7 @@ static struct rdma_id_private *cma_id_fr |
| return id_priv; |
| } |
| |
| -static inline int cma_user_data_offset(struct rdma_id_private *id_priv) |
| +static inline u8 cma_user_data_offset(struct rdma_id_private *id_priv) |
| { |
| return cma_family(id_priv) == AF_IB ? 0 : sizeof(struct cma_hdr); |
| } |
| @@ -1942,7 +1942,8 @@ static int cma_req_handler(struct ib_cm_ |
| struct rdma_id_private *listen_id, *conn_id = NULL; |
| struct rdma_cm_event event; |
| struct net_device *net_dev; |
| - int offset, ret; |
| + u8 offset; |
| + int ret; |
| |
| listen_id = cma_id_from_event(cm_id, ib_event, &net_dev); |
| if (IS_ERR(listen_id)) |
| @@ -3440,7 +3441,8 @@ static int cma_resolve_ib_udp(struct rdm |
| struct ib_cm_sidr_req_param req; |
| struct ib_cm_id *id; |
| void *private_data; |
| - int offset, ret; |
| + u8 offset; |
| + int ret; |
| |
| memset(&req, 0, sizeof req); |
| offset = cma_user_data_offset(id_priv); |
| @@ -3497,7 +3499,8 @@ static int cma_connect_ib(struct rdma_id |
| struct rdma_route *route; |
| void *private_data; |
| struct ib_cm_id *id; |
| - int offset, ret; |
| + u8 offset; |
| + int ret; |
| |
| memset(&req, 0, sizeof req); |
| offset = cma_user_data_offset(id_priv); |