aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/input/ipaccess.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-03-24 08:40:55 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-03-24 08:40:55 +0100
commitb3121c5b3f1f76c742ce36b75951ef8a3fde46ae (patch)
treebd6ff8ceaeeb58f873740162d5a23abb68000eb1 /openbsc/src/input/ipaccess.c
parentf5284ae1cf8babc1567b33f469e20a66a73fcd9e (diff)
ipa: Handle corrupt incoming messages without crashing
Attempt to read the three byte IPA header. If we read 0 then the socket can be closed otherwise we need to read three bytes, if we don't we do have a failure. After having parsed the header we need to evaluate the length, if the length is bigger than would fit into our buffer we will ignore that and print an error. This is fixing a crash when the BTS is crashing...
Diffstat (limited to 'openbsc/src/input/ipaccess.c')
-rw-r--r--openbsc/src/input/ipaccess.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index 91d267cb0..3e266894b 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -289,14 +289,14 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
/* first read our 3-byte header */
hh = (struct ipaccess_head *) msg->data;
- ret = recv(bfd->fd, msg->data, 3, 0);
- if (ret < 0) {
- if (errno != EAGAIN)
- LOGP(DINP, LOGL_ERROR, "recv error %d %s\n", ret, strerror(errno));
+ ret = recv(bfd->fd, msg->data, sizeof(*hh), 0);
+ if (ret == 0) {
msgb_free(msg);
*error = ret;
return NULL;
- } else if (ret == 0) {
+ } else if (ret != sizeof(*hh)) {
+ if (errno != EAGAIN)
+ LOGP(DINP, LOGL_ERROR, "recv error %d %s\n", ret, strerror(errno));
msgb_free(msg);
*error = ret;
return NULL;
@@ -307,9 +307,17 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
/* then read te length as specified in header */
msg->l2h = msg->data + sizeof(*hh);
len = ntohs(hh->len);
+
+ if (len < 0 || TS1_ALLOC_SIZE < len + sizeof(*hh)) {
+ LOGP(DINP, LOGL_ERROR, "Can not read this packet. %d avail\n", len);
+ msgb_free(msg);
+ *error = -EIO;
+ return NULL;
+ }
+
ret = recv(bfd->fd, msg->l2h, len, 0);
if (ret < len) {
- LOGP(DINP, LOGL_ERROR, "short read!\n");
+ LOGP(DINP, LOGL_ERROR, "short read! Got %d from %d\n", ret, len);
msgb_free(msg);
*error = -EIO;
return NULL;