laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/29361 )
Change subject: pcu_sock: check size of primitive ......................................................................
pcu_sock: check size of primitive
The pcu_sock interface in osmo-bts does check the size of the primitives it receives. Lets do the same in osmo-bsc as well.
Change-Id: I247c6f4b5a7a22d17a060a558c4ceb9221ca7351 Related: OS#5198 --- M include/osmocom/bsc/pcu_if.h M src/osmo-bsc/pcu_sock.c 2 files changed, 21 insertions(+), 2 deletions(-)
Approvals: Jenkins Builder: Verified neels: Looks good to me, but someone else must approve pespin: Looks good to me, approved laforge: Looks good to me, approved
diff --git a/include/osmocom/bsc/pcu_if.h b/include/osmocom/bsc/pcu_if.h index 1f398b4..3c34cdf 100644 --- a/include/osmocom/bsc/pcu_if.h +++ b/include/osmocom/bsc/pcu_if.h @@ -5,6 +5,8 @@
extern int pcu_direct;
+#define PCUIF_HDR_SIZE (sizeof(struct gsm_pcu_if) - sizeof(((struct gsm_pcu_if *)0)->u)) + struct pcu_sock_state { struct gsm_network *net; struct osmo_fd listen_bfd; /* fd for listen socket */ diff --git a/src/osmo-bsc/pcu_sock.c b/src/osmo-bsc/pcu_sock.c index 2cf1ab5..1af9a9d 100644 --- a/src/osmo-bsc/pcu_sock.c +++ b/src/osmo-bsc/pcu_sock.c @@ -448,8 +448,17 @@ return rc; }
+#define CHECK_IF_MSG_SIZE(prim_len, prim_msg) \ + do { \ + size_t _len = PCUIF_HDR_SIZE + sizeof(prim_msg); \ + if (prim_len < _len) { \ + LOGP(DPCU, LOGL_ERROR, "Received %zu bytes on PCU Socket, but primitive %s " \ + "size is %zu, discarding\n", prim_len, #prim_msg, _len); \ + return -EINVAL; \ + } \ + } while (0) static int pcu_rx(struct gsm_network *net, uint8_t msg_type, - struct gsm_pcu_if *pcu_prim) + struct gsm_pcu_if *pcu_prim, size_t prim_len) { int rc = 0; struct gsm_bts *bts; @@ -460,6 +469,7 @@ switch (msg_type) { case PCU_IF_MSG_DATA_REQ: case PCU_IF_MSG_PAG_REQ: + CHECK_IF_MSG_SIZE(prim_len, pcu_prim->u.data_req); rc = pcu_rx_data_req(bts, msg_type, &pcu_prim->u.data_req); break; default: @@ -574,7 +584,14 @@ goto close; }
- rc = pcu_rx(state->net, pcu_prim->msg_type, pcu_prim); + if (rc < PCUIF_HDR_SIZE) { + LOGP(DPCU, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive hdr size " + "is %zu, discarding\n", rc, PCUIF_HDR_SIZE); + msgb_free(msg); + return 0; + } + + rc = pcu_rx(state->net, pcu_prim->msg_type, pcu_prim, rc);
/* as we always synchronously process the message in pcu_rx() and * its callbacks, we can free the message here. */