]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
caif: reduce stack size, again
authorArnd Bergmann <arnd@arndb.de>
Fri, 20 Jun 2025 11:22:39 +0000 (13:22 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 23 Jun 2025 23:58:43 +0000 (16:58 -0700)
I tried to fix the stack usage in this function a couple of years ago,
but there is still a problem with the latest gcc versions in some
configurations:

net/caif/cfctrl.c:553:1: error: the frame size of 1296 bytes is larger than 1280 bytes [-Werror=frame-larger-than=]

Reduce this once again, with a separate cfctrl_link_setup() function that
holds the bulk of all the local variables. It also turns out that the
param[] array that takes up a large portion of the stack is write-only
and can be left out here.

Fixes: ce6289661b14 ("caif: reduce stack size with KASAN")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://patch.msgid.link/20250620112244.3425554-1-arnd@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/caif/cfctrl.c

index 20139fa1be1fff45b152daf996397fa909a6baad..06b604cf9d58c0dd30008d8c34362e58ada60557 100644 (file)
@@ -351,17 +351,154 @@ int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
        return found;
 }
 
+static int cfctrl_link_setup(struct cfctrl *cfctrl, struct cfpkt *pkt, u8 cmdrsp)
+{
+       u8 len;
+       u8 linkid = 0;
+       enum cfctrl_srv serv;
+       enum cfctrl_srv servtype;
+       u8 endpoint;
+       u8 physlinkid;
+       u8 prio;
+       u8 tmp;
+       u8 *cp;
+       int i;
+       struct cfctrl_link_param linkparam;
+       struct cfctrl_request_info rsp, *req;
+
+       memset(&linkparam, 0, sizeof(linkparam));
+
+       tmp = cfpkt_extr_head_u8(pkt);
+
+       serv = tmp & CFCTRL_SRV_MASK;
+       linkparam.linktype = serv;
+
+       servtype = tmp >> 4;
+       linkparam.chtype = servtype;
+
+       tmp = cfpkt_extr_head_u8(pkt);
+       physlinkid = tmp & 0x07;
+       prio = tmp >> 3;
+
+       linkparam.priority = prio;
+       linkparam.phyid = physlinkid;
+       endpoint = cfpkt_extr_head_u8(pkt);
+       linkparam.endpoint = endpoint & 0x03;
+
+       switch (serv) {
+       case CFCTRL_SRV_VEI:
+       case CFCTRL_SRV_DBG:
+               if (CFCTRL_ERR_BIT & cmdrsp)
+                       break;
+               /* Link ID */
+               linkid = cfpkt_extr_head_u8(pkt);
+               break;
+       case CFCTRL_SRV_VIDEO:
+               tmp = cfpkt_extr_head_u8(pkt);
+               linkparam.u.video.connid = tmp;
+               if (CFCTRL_ERR_BIT & cmdrsp)
+                       break;
+               /* Link ID */
+               linkid = cfpkt_extr_head_u8(pkt);
+               break;
+
+       case CFCTRL_SRV_DATAGRAM:
+               linkparam.u.datagram.connid = cfpkt_extr_head_u32(pkt);
+               if (CFCTRL_ERR_BIT & cmdrsp)
+                       break;
+               /* Link ID */
+               linkid = cfpkt_extr_head_u8(pkt);
+               break;
+       case CFCTRL_SRV_RFM:
+               /* Construct a frame, convert
+                * DatagramConnectionID
+                * to network format long and copy it out...
+                */
+               linkparam.u.rfm.connid = cfpkt_extr_head_u32(pkt);
+               cp = (u8 *) linkparam.u.rfm.volume;
+               for (tmp = cfpkt_extr_head_u8(pkt);
+                    cfpkt_more(pkt) && tmp != '\0';
+                    tmp = cfpkt_extr_head_u8(pkt))
+                       *cp++ = tmp;
+               *cp = '\0';
+
+               if (CFCTRL_ERR_BIT & cmdrsp)
+                       break;
+               /* Link ID */
+               linkid = cfpkt_extr_head_u8(pkt);
+
+               break;
+       case CFCTRL_SRV_UTIL:
+               /* Construct a frame, convert
+                * DatagramConnectionID
+                * to network format long and copy it out...
+                */
+               /* Fifosize KB */
+               linkparam.u.utility.fifosize_kb = cfpkt_extr_head_u16(pkt);
+               /* Fifosize bufs */
+               linkparam.u.utility.fifosize_bufs = cfpkt_extr_head_u16(pkt);
+               /* name */
+               cp = (u8 *) linkparam.u.utility.name;
+               caif_assert(sizeof(linkparam.u.utility.name)
+                            >= UTILITY_NAME_LENGTH);
+               for (i = 0; i < UTILITY_NAME_LENGTH && cfpkt_more(pkt); i++) {
+                       tmp = cfpkt_extr_head_u8(pkt);
+                       *cp++ = tmp;
+               }
+               /* Length */
+               len = cfpkt_extr_head_u8(pkt);
+               linkparam.u.utility.paramlen = len;
+               /* Param Data */
+               cp = linkparam.u.utility.params;
+               while (cfpkt_more(pkt) && len--) {
+                       tmp = cfpkt_extr_head_u8(pkt);
+                       *cp++ = tmp;
+               }
+               if (CFCTRL_ERR_BIT & cmdrsp)
+                       break;
+               /* Link ID */
+               linkid = cfpkt_extr_head_u8(pkt);
+               /* Length */
+               len = cfpkt_extr_head_u8(pkt);
+               /* Param Data */
+               cfpkt_extr_head(pkt, NULL, len);
+               break;
+       default:
+               pr_warn("Request setup, invalid type (%d)\n", serv);
+               return -1;
+       }
+
+       rsp.cmd = CFCTRL_CMD_LINK_SETUP;
+       rsp.param = linkparam;
+       spin_lock_bh(&cfctrl->info_list_lock);
+       req = cfctrl_remove_req(cfctrl, &rsp);
+
+       if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) ||
+               cfpkt_erroneous(pkt)) {
+               pr_err("Invalid O/E bit or parse error "
+                               "on CAIF control channel\n");
+               cfctrl->res.reject_rsp(cfctrl->serv.layer.up, 0,
+                                      req ? req->client_layer : NULL);
+       } else {
+               cfctrl->res.linksetup_rsp(cfctrl->serv.layer.up, linkid,
+                                         serv, physlinkid,
+                                         req ?  req->client_layer : NULL);
+       }
+
+       kfree(req);
+
+       spin_unlock_bh(&cfctrl->info_list_lock);
+
+       return 0;
+}
+
 static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
 {
        u8 cmdrsp;
        u8 cmd;
-       int ret = -1;
-       u8 len;
-       u8 param[255];
+       int ret = 0;
        u8 linkid = 0;
        struct cfctrl *cfctrl = container_obj(layer);
-       struct cfctrl_request_info rsp, *req;
-
 
        cmdrsp = cfpkt_extr_head_u8(pkt);
        cmd = cmdrsp & CFCTRL_CMD_MASK;
@@ -374,150 +511,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
 
        switch (cmd) {
        case CFCTRL_CMD_LINK_SETUP:
-               {
-                       enum cfctrl_srv serv;
-                       enum cfctrl_srv servtype;
-                       u8 endpoint;
-                       u8 physlinkid;
-                       u8 prio;
-                       u8 tmp;
-                       u8 *cp;
-                       int i;
-                       struct cfctrl_link_param linkparam;
-                       memset(&linkparam, 0, sizeof(linkparam));
-
-                       tmp = cfpkt_extr_head_u8(pkt);
-
-                       serv = tmp & CFCTRL_SRV_MASK;
-                       linkparam.linktype = serv;
-
-                       servtype = tmp >> 4;
-                       linkparam.chtype = servtype;
-
-                       tmp = cfpkt_extr_head_u8(pkt);
-                       physlinkid = tmp & 0x07;
-                       prio = tmp >> 3;
-
-                       linkparam.priority = prio;
-                       linkparam.phyid = physlinkid;
-                       endpoint = cfpkt_extr_head_u8(pkt);
-                       linkparam.endpoint = endpoint & 0x03;
-
-                       switch (serv) {
-                       case CFCTRL_SRV_VEI:
-                       case CFCTRL_SRV_DBG:
-                               if (CFCTRL_ERR_BIT & cmdrsp)
-                                       break;
-                               /* Link ID */
-                               linkid = cfpkt_extr_head_u8(pkt);
-                               break;
-                       case CFCTRL_SRV_VIDEO:
-                               tmp = cfpkt_extr_head_u8(pkt);
-                               linkparam.u.video.connid = tmp;
-                               if (CFCTRL_ERR_BIT & cmdrsp)
-                                       break;
-                               /* Link ID */
-                               linkid = cfpkt_extr_head_u8(pkt);
-                               break;
-
-                       case CFCTRL_SRV_DATAGRAM:
-                               linkparam.u.datagram.connid =
-                                   cfpkt_extr_head_u32(pkt);
-                               if (CFCTRL_ERR_BIT & cmdrsp)
-                                       break;
-                               /* Link ID */
-                               linkid = cfpkt_extr_head_u8(pkt);
-                               break;
-                       case CFCTRL_SRV_RFM:
-                               /* Construct a frame, convert
-                                * DatagramConnectionID
-                                * to network format long and copy it out...
-                                */
-                               linkparam.u.rfm.connid =
-                                   cfpkt_extr_head_u32(pkt);
-                               cp = (u8 *) linkparam.u.rfm.volume;
-                               for (tmp = cfpkt_extr_head_u8(pkt);
-                                    cfpkt_more(pkt) && tmp != '\0';
-                                    tmp = cfpkt_extr_head_u8(pkt))
-                                       *cp++ = tmp;
-                               *cp = '\0';
-
-                               if (CFCTRL_ERR_BIT & cmdrsp)
-                                       break;
-                               /* Link ID */
-                               linkid = cfpkt_extr_head_u8(pkt);
-
-                               break;
-                       case CFCTRL_SRV_UTIL:
-                               /* Construct a frame, convert
-                                * DatagramConnectionID
-                                * to network format long and copy it out...
-                                */
-                               /* Fifosize KB */
-                               linkparam.u.utility.fifosize_kb =
-                                   cfpkt_extr_head_u16(pkt);
-                               /* Fifosize bufs */
-                               linkparam.u.utility.fifosize_bufs =
-                                   cfpkt_extr_head_u16(pkt);
-                               /* name */
-                               cp = (u8 *) linkparam.u.utility.name;
-                               caif_assert(sizeof(linkparam.u.utility.name)
-                                            >= UTILITY_NAME_LENGTH);
-                               for (i = 0;
-                                    i < UTILITY_NAME_LENGTH
-                                    && cfpkt_more(pkt); i++) {
-                                       tmp = cfpkt_extr_head_u8(pkt);
-                                       *cp++ = tmp;
-                               }
-                               /* Length */
-                               len = cfpkt_extr_head_u8(pkt);
-                               linkparam.u.utility.paramlen = len;
-                               /* Param Data */
-                               cp = linkparam.u.utility.params;
-                               while (cfpkt_more(pkt) && len--) {
-                                       tmp = cfpkt_extr_head_u8(pkt);
-                                       *cp++ = tmp;
-                               }
-                               if (CFCTRL_ERR_BIT & cmdrsp)
-                                       break;
-                               /* Link ID */
-                               linkid = cfpkt_extr_head_u8(pkt);
-                               /* Length */
-                               len = cfpkt_extr_head_u8(pkt);
-                               /* Param Data */
-                               cfpkt_extr_head(pkt, &param, len);
-                               break;
-                       default:
-                               pr_warn("Request setup, invalid type (%d)\n",
-                                       serv);
-                               goto error;
-                       }
-
-                       rsp.cmd = cmd;
-                       rsp.param = linkparam;
-                       spin_lock_bh(&cfctrl->info_list_lock);
-                       req = cfctrl_remove_req(cfctrl, &rsp);
-
-                       if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) ||
-                               cfpkt_erroneous(pkt)) {
-                               pr_err("Invalid O/E bit or parse error "
-                                               "on CAIF control channel\n");
-                               cfctrl->res.reject_rsp(cfctrl->serv.layer.up,
-                                                      0,
-                                                      req ? req->client_layer
-                                                      : NULL);
-                       } else {
-                               cfctrl->res.linksetup_rsp(cfctrl->serv.
-                                                         layer.up, linkid,
-                                                         serv, physlinkid,
-                                                         req ? req->
-                                                         client_layer : NULL);
-                       }
-
-                       kfree(req);
-
-                       spin_unlock_bh(&cfctrl->info_list_lock);
-               }
+               ret = cfctrl_link_setup(cfctrl, pkt, cmdrsp);
                break;
        case CFCTRL_CMD_LINK_DESTROY:
                linkid = cfpkt_extr_head_u8(pkt);
@@ -544,9 +538,9 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
                break;
        default:
                pr_err("Unrecognized Control Frame\n");
+               ret = -1;
                goto error;
        }
-       ret = 0;
 error:
        cfpkt_destroy(pkt);
        return ret;