Bladeren bron

Add checks of IOCRBlockReq PDUs

The IOCRBlockReq PDUs need to be checked against the resources
available. This change adds such checks and error responses when
the checks fail.
Mattias Nilsson 2 jaren geleden
bovenliggende
commit
18db689365
3 gewijzigde bestanden met toevoegingen van 63 en 24 verwijderingen
  1. 25 3
      src/device/pf_block_reader.c
  2. 2 1
      src/device/pf_block_reader.h
  3. 36 20
      src/device/pf_cmrpc.c

+ 25 - 3
src/device/pf_block_reader.c

@@ -244,8 +244,9 @@ static void pf_get_frame_descriptor (
  * @param p_info           InOut: The parser state.
  * @param p_pos            InOut: Position in the buffer.
  * @param p_ae             Out:   Destination buffer.
+ * @return 0 on success, -1 if out of resources.
  */
-static void pf_get_iocr_api_entry (
+static int pf_get_iocr_api_entry (
    pf_get_info_t * p_info,
    uint16_t * p_pos,
    pf_api_entry_t * p_ae)
@@ -255,16 +256,25 @@ static void pf_get_iocr_api_entry (
    p_ae->api = pf_get_uint32 (p_info, p_pos);
 
    p_ae->nbr_io_data = pf_get_uint16 (p_info, p_pos);
+   if (p_ae->nbr_io_data > NELEMENTS (p_ae->io_data))
+   {
+      return -1;
+   }
    for (ix = 0; ix < p_ae->nbr_io_data; ix++)
    {
       pf_get_frame_descriptor (p_info, p_pos, &p_ae->io_data[ix]);
    }
 
    p_ae->nbr_iocs = pf_get_uint16 (p_info, p_pos);
+   if (p_ae->nbr_iocs > NELEMENTS (p_ae->iocs))
+   {
+      return -1;
+   }
    for (ix = 0; ix < p_ae->nbr_iocs; ix++)
    {
       pf_get_frame_descriptor (p_info, p_pos, &p_ae->iocs[ix]);
    }
+   return 0;
 }
 
 /**
@@ -383,7 +393,7 @@ void pf_get_ar_param (pf_get_info_t * p_info, uint16_t * p_pos, pf_ar_t * p_ar)
    p_ar->ar_param.cm_initiator_station_name[str_len] = '\0';
 }
 
-void pf_get_iocr_param (
+int pf_get_iocr_param (
    pf_get_info_t * p_info,
    uint16_t * p_pos,
    uint16_t ix,
@@ -430,10 +440,22 @@ void pf_get_iocr_param (
       &p_ar->iocrs[ix].param.iocr_multicast_mac_add);
 
    p_ar->iocrs[ix].param.nbr_apis = pf_get_uint16 (p_info, p_pos);
+   if (p_ar->iocrs[ix].param.nbr_apis > PNET_MAX_API)
+   {
+      return -1;
+   }
    for (iy = 0; iy < p_ar->iocrs[ix].param.nbr_apis; iy++)
    {
-      pf_get_iocr_api_entry (p_info, p_pos, &p_ar->iocrs[ix].param.apis[iy]);
+      if (
+         pf_get_iocr_api_entry (
+            p_info,
+            p_pos,
+            &p_ar->iocrs[ix].param.apis[iy]) != 0)
+      {
+         return -1;
+      }
    }
+   return 0;
 }
 
 void pf_get_exp_api_module (

+ 2 - 1
src/device/pf_block_reader.h

@@ -109,8 +109,9 @@ void pf_get_ar_param (pf_get_info_t * p_info, uint16_t * p_pos, pf_ar_t * p_ar);
  * @param p_pos            InOut: Position in the buffer.
  * @param ix               In:    The current index into p_ar->iocr[].
  * @param p_ar             Out:   Contains the destination structure.
+ * @return 0 on success, -1 if out of resources
  */
-void pf_get_iocr_param (
+int pf_get_iocr_param (
    pf_get_info_t * p_info,
    uint16_t * p_pos,
    uint16_t ix,

+ 36 - 20
src/device/pf_cmrpc.c

@@ -1255,16 +1255,47 @@ static int pf_cmrpc_rm_connect_interpret_ind (
             }
             break;
          case PF_BT_IOCR_BLOCK_REQ:
-            if (p_ar->nbr_iocrs < PNET_MAX_CR)
+            if (!(p_ar->nbr_iocrs < PNET_MAX_CR))
             {
-               /* Before it is incremented at the end of this block, the
-               p_ar->nbr_iocrs value is the same as CREP */
+               LOG_ERROR (
+                  PF_RPC_LOG,
+                  "CMRPC(%d): Too many CR given. Max %u CR per AR supported\n",
+                  __LINE__,
+                  PNET_MAX_CR);
+               pf_set_error (
+                  &p_sess->rpc_result,
+                  PNET_ERROR_CODE_CONNECT,
+                  PNET_ERROR_DECODE_PNIO,
+                  PNET_ERROR_CODE_1_CMRPC,
+                  PNET_ERROR_CODE_2_CMRPC_WRONG_BLOCK_COUNT);
+               ret = -1;
+            }
+            else if (
                pf_get_iocr_param (
                   &p_sess->get_info,
                   p_pos,
                   p_ar->nbr_iocrs,
-                  p_ar);
-
+                  p_ar) != 0)
+            {
+               LOG_ERROR (
+                  PF_RPC_LOG,
+                  "CMRPC(%d): Too many CR resources requested."
+                  " Check that the controller (PLC) does not request more"
+                  " modules or submodules than P-Net has been configured"
+                  " to support.\n",
+                  __LINE__);
+               pf_set_error (
+                  &p_sess->rpc_result,
+                  PNET_ERROR_CODE_CONNECT,
+                  PNET_ERROR_DECODE_PNIO,
+                  PNET_ERROR_CODE_1_CMRPC,
+                  PNET_ERROR_CODE_2_CMRPC_OUT_OF_PCA_RESOURCES);
+               ret = -1;
+            }
+            else
+            {
+               /* Before it is incremented at the end of this block, the
+               p_ar->nbr_iocrs value is the same as CREP */
                LOG_DEBUG (
                   PF_RPC_LOG,
                   "CMRPC(%d): Requested send cycle time: %u (in 1/32 of "
@@ -1329,21 +1360,6 @@ static int pf_cmrpc_rm_connect_interpret_ind (
                   }
                }
             }
-            else
-            {
-               LOG_ERROR (
-                  PF_RPC_LOG,
-                  "CMRPC(%d): Too many CR given. Max %u CR per AR supported\n",
-                  __LINE__,
-                  PNET_MAX_CR);
-               pf_set_error (
-                  &p_sess->rpc_result,
-                  PNET_ERROR_CODE_CONNECT,
-                  PNET_ERROR_DECODE_PNIO,
-                  PNET_ERROR_CODE_1_CMRPC,
-                  PNET_ERROR_CODE_2_CMRPC_WRONG_BLOCK_COUNT);
-               ret = -1;
-            }
             break;
          case PF_BT_EXPECTED_SUBMODULE_BLOCK:
             pf_get_exp_api_module (&p_sess->get_info, p_pos, p_ar);