mei: revamp mei extension header structure layout.
authorTomas Winkler <tomas.winkler@intel.com>
Mon, 21 Jun 2021 19:37:56 +0000 (22:37 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 22 Jun 2021 10:40:31 +0000 (12:40 +0200)
The mei extension header was build as array of flexible structures
which will not work if actually more headers are added.
(Currently only vtag header was used).
Sparse reports:

drivers/misc/mei/hw.h:253:32: warning: array of flexible structures

Use basic type u8 for the variable sized extension.
Define explicitly mei_ext_hdr_vtag structure.
And also fix mei_ext_next() function to point correctly to the
end of the header.

Note: the headers are part of firmware interface and need to be __packed.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20210621193756.134027-2-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/client.c
drivers/misc/mei/hw.h
drivers/misc/mei/interrupt.c

index 18e4947..96f4e59 100644 (file)
@@ -1726,12 +1726,15 @@ nortpm:
        return rets;
 }
 
-static inline u8 mei_ext_hdr_set_vtag(struct mei_ext_hdr *ext, u8 vtag)
+static inline u8 mei_ext_hdr_set_vtag(void *ext, u8 vtag)
 {
-       ext->type = MEI_EXT_HDR_VTAG;
-       ext->ext_payload[0] = vtag;
-       ext->length = mei_data2slots(sizeof(*ext));
-       return ext->length;
+       struct mei_ext_hdr_vtag *vtag_hdr = ext;
+
+       vtag_hdr->hdr.type = MEI_EXT_HDR_VTAG;
+       vtag_hdr->hdr.length = mei_data2slots(sizeof(*vtag_hdr));
+       vtag_hdr->vtag = vtag;
+       vtag_hdr->reserved = 0;
+       return vtag_hdr->hdr.length;
 }
 
 /**
@@ -1745,7 +1748,6 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
 {
        size_t hdr_len;
        struct mei_ext_meta_hdr *meta;
-       struct mei_ext_hdr *ext;
        struct mei_msg_hdr *mei_hdr;
        bool is_ext, is_vtag;
 
@@ -1764,7 +1766,7 @@ static struct mei_msg_hdr *mei_msg_hdr_init(const struct mei_cl_cb *cb)
 
        hdr_len += sizeof(*meta);
        if (is_vtag)
-               hdr_len += sizeof(*ext);
+               hdr_len += sizeof(struct mei_ext_hdr_vtag);
 
 setup_hdr:
        mei_hdr = kzalloc(hdr_len, GFP_KERNEL);
index 47ef242..dfd60c9 100644 (file)
@@ -235,9 +235,8 @@ enum mei_ext_hdr_type {
 struct mei_ext_hdr {
        u8 type;
        u8 length;
-       u8 ext_payload[2];
-       u8 hdr[];
-};
+       u8 data[];
+} __packed;
 
 /**
  * struct mei_ext_meta_hdr - extend header meta data
@@ -250,8 +249,21 @@ struct mei_ext_meta_hdr {
        u8 count;
        u8 size;
        u8 reserved[2];
-       struct mei_ext_hdr hdrs[];
-};
+       u8 hdrs[];
+} __packed;
+
+/**
+ * struct mei_ext_hdr_vtag - extend header for vtag
+ *
+ * @hdr: standard extend header
+ * @vtag: virtual tag
+ * @reserved: reserved
+ */
+struct mei_ext_hdr_vtag {
+       struct mei_ext_hdr hdr;
+       u8 vtag;
+       u8 reserved;
+} __packed;
 
 /*
  * Extended header iterator functions
@@ -266,7 +278,7 @@ struct mei_ext_meta_hdr {
  */
 static inline struct mei_ext_hdr *mei_ext_begin(struct mei_ext_meta_hdr *meta)
 {
-       return meta->hdrs;
+       return (struct mei_ext_hdr *)meta->hdrs;
 }
 
 /**
@@ -295,7 +307,7 @@ static inline bool mei_ext_last(struct mei_ext_meta_hdr *meta,
  */
 static inline struct mei_ext_hdr *mei_ext_next(struct mei_ext_hdr *ext)
 {
-       return (struct mei_ext_hdr *)(ext->hdr + (ext->length * 4));
+       return (struct mei_ext_hdr *)((u8 *)ext + (ext->length * 4));
 }
 
 /**
index aab3ebf..a67f4f2 100644 (file)
@@ -123,13 +123,13 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
 
        if (mei_hdr->extended) {
                struct mei_ext_hdr *ext;
-               struct mei_ext_hdr *vtag = NULL;
+               struct mei_ext_hdr_vtag *vtag_hdr = NULL;
 
                ext = mei_ext_begin(meta);
                do {
                        switch (ext->type) {
                        case MEI_EXT_HDR_VTAG:
-                               vtag = ext;
+                               vtag_hdr = (struct mei_ext_hdr_vtag *)ext;
                                break;
                        case MEI_EXT_HDR_NONE:
                                fallthrough;
@@ -141,20 +141,20 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
                        ext = mei_ext_next(ext);
                } while (!mei_ext_last(meta, ext));
 
-               if (!vtag) {
+               if (!vtag_hdr) {
                        cl_dbg(dev, cl, "vtag not found in extended header.\n");
                        cb->status = -EPROTO;
                        goto discard;
                }
 
-               cl_dbg(dev, cl, "vtag: %d\n", vtag->ext_payload[0]);
-               if (cb->vtag && cb->vtag != vtag->ext_payload[0]) {
+               cl_dbg(dev, cl, "vtag: %d\n", vtag_hdr->vtag);
+               if (cb->vtag && cb->vtag != vtag_hdr->vtag) {
                        cl_err(dev, cl, "mismatched tag: %d != %d\n",
-                              cb->vtag, vtag->ext_payload[0]);
+                              cb->vtag, vtag_hdr->vtag);
                        cb->status = -EPROTO;
                        goto discard;
                }
-               cb->vtag = vtag->ext_payload[0];
+               cb->vtag = vtag_hdr->vtag;
        }
 
        if (!mei_cl_is_connected(cl)) {
@@ -331,7 +331,6 @@ int mei_irq_read_handler(struct mei_device *dev,
        struct mei_ext_meta_hdr *meta_hdr = NULL;
        struct mei_cl *cl;
        int ret;
-       u32 ext_meta_hdr_u32;
        u32 hdr_size_left;
        u32 hdr_size_ext;
        int i;
@@ -367,14 +366,12 @@ int mei_irq_read_handler(struct mei_device *dev,
 
        if (mei_hdr->extended) {
                if (!dev->rd_msg_hdr[1]) {
-                       ext_meta_hdr_u32 = mei_read_hdr(dev);
-                       dev->rd_msg_hdr[1] = ext_meta_hdr_u32;
+                       dev->rd_msg_hdr[1] = mei_read_hdr(dev);
                        dev->rd_msg_hdr_count++;
                        (*slots)--;
-                       dev_dbg(dev->dev, "extended header is %08x\n",
-                               ext_meta_hdr_u32);
+                       dev_dbg(dev->dev, "extended header is %08x\n", dev->rd_msg_hdr[1]);
                }
-               meta_hdr = ((struct mei_ext_meta_hdr *)dev->rd_msg_hdr + 1);
+               meta_hdr = ((struct mei_ext_meta_hdr *)&dev->rd_msg_hdr[1]);
                if (check_add_overflow((u32)sizeof(*meta_hdr),
                                       mei_slots2data(meta_hdr->size),
                                       &hdr_size_ext)) {