mei: check for error returned from mei_hbuf_empty_slots()
authorTomas Winkler <tomas.winkler@intel.com>
Thu, 12 Jul 2018 14:10:08 +0000 (17:10 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Jul 2018 14:23:19 +0000 (16:23 +0200)
mei_hbuf_empty_slots() may return with an error in case
of circular buffer overflow. This type of error may
be caused only by a bug. However currently, the error
won't be detected due signed type promotion in comparison to u32.
We add explicit check for less then zero and explicit cast
in comparison to suppress singn-compare warning.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/client.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-txe.c
drivers/misc/mei/interrupt.c

index 8d6197a88b54551d07de68d2c4387add2a7fbc5a..f8fb7589192e89ae313047537cafd0d05fbd2103 100644 (file)
@@ -865,8 +865,10 @@ int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
        slots = mei_hbuf_empty_slots(dev);
+       if (slots < 0)
+               return -EOVERFLOW;
 
-       if (slots < msg_slots)
+       if ((u32)slots < msg_slots)
                return -EMSGSIZE;
 
        ret = mei_cl_send_disconnect(cl, cb);
@@ -1054,12 +1056,15 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
        int rets;
 
        msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
-       slots = mei_hbuf_empty_slots(dev);
 
        if (mei_cl_is_other_connecting(cl))
                return 0;
 
-       if (slots < msg_slots)
+       slots = mei_hbuf_empty_slots(dev);
+       if (slots < 0)
+               return -EOVERFLOW;
+
+       if ((u32)slots < msg_slots)
                return -EMSGSIZE;
 
        rets = mei_cl_send_connect(cl, cb);
@@ -1296,8 +1301,10 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
        slots = mei_hbuf_empty_slots(dev);
+       if (slots < 0)
+               return -EOVERFLOW;
 
-       if (slots < msg_slots)
+       if ((u32)slots < msg_slots)
                return -EMSGSIZE;
 
        request = mei_cl_notify_fop2req(cb->fop_type);
@@ -1573,6 +1580,9 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
        }
 
        slots = mei_hbuf_empty_slots(dev);
+       if (slots < 0)
+               return -EOVERFLOW;
+
        len = buf->size - cb->buf_idx;
        msg_slots = mei_data2slots(len);
 
@@ -1581,11 +1591,11 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
        mei_hdr.reserved = 0;
        mei_hdr.internal = cb->internal;
 
-       if (slots >= msg_slots) {
+       if ((u32)slots >= msg_slots) {
                mei_hdr.length = len;
                mei_hdr.msg_complete = 1;
        /* Split the message only if we can write the whole host buffer */
-       } else if (slots == dev->hbuf_depth) {
+       } else if ((u32)slots == dev->hbuf_depth) {
                msg_slots = slots;
                len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
                mei_hdr.length = len;
index 334ab02e1de20b5f8ade7d76aeca4955ac5fdb53..a12b464bc0b41ce0d97bd5053837413530234048 100644 (file)
@@ -540,8 +540,11 @@ static int mei_me_hbuf_write(struct mei_device *dev,
        empty_slots = mei_hbuf_empty_slots(dev);
        dev_dbg(dev->dev, "empty slots = %hu.\n", empty_slots);
 
+       if (empty_slots < 0)
+               return -EOVERFLOW;
+
        dw_cnt = mei_data2slots(length);
-       if (empty_slots < 0 || dw_cnt > empty_slots)
+       if (dw_cnt > (u32)empty_slots)
                return -EMSGSIZE;
 
        mei_me_hcbww_write(dev, *((u32 *) header));
index c2c8993e2a511e64d18fb5da57bd5eb507e1d2e2..4c1acf68089ef4fffddc453b5a640b057324fa2b 100644 (file)
@@ -709,7 +709,7 @@ static int mei_txe_write(struct mei_device *dev,
        struct mei_txe_hw *hw = to_txe_hw(dev);
        unsigned long rem;
        unsigned long length;
-       int slots = dev->hbuf_depth;
+       u32 slots = dev->hbuf_depth;
        u32 *reg_buf = (u32 *)buf;
        u32 dw_cnt;
        int i;
index b0b8f18a85e3e132d7741e9daab53fe9270b1b8a..01990e339e76e2c5dd48f06d30760862a881e821 100644 (file)
@@ -173,10 +173,12 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
        int slots;
        int ret;
 
-       slots = mei_hbuf_empty_slots(dev);
        msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_response));
+       slots = mei_hbuf_empty_slots(dev);
+       if (slots < 0)
+               return -EOVERFLOW;
 
-       if (slots < msg_slots)
+       if ((u32)slots < msg_slots)
                return -EMSGSIZE;
 
        ret = mei_hbm_cl_disconnect_rsp(dev, cl);
@@ -208,8 +210,10 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
        slots = mei_hbuf_empty_slots(dev);
+       if (slots < 0)
+               return -EOVERFLOW;
 
-       if (slots < msg_slots)
+       if ((u32)slots < msg_slots)
                return -EMSGSIZE;
 
        ret = mei_hbm_cl_flow_control_req(dev, cl);
@@ -365,7 +369,10 @@ int mei_irq_write_handler(struct mei_device *dev, struct list_head *cmpl_list)
                return 0;
 
        slots = mei_hbuf_empty_slots(dev);
-       if (slots <= 0)
+       if (slots < 0)
+               return -EOVERFLOW;
+
+       if (slots == 0)
                return -EMSGSIZE;
 
        /* complete all waiting for write CB */