core: Limit maximum size of an assembled MCTP message

If libmctp receives sequence of fragment MCTP packets and never receives
EOM packet, this will cause heap memory to grow without bounds. This
commit puts an upper cap on maximum MCTP message size. This should
protect us from any malicious device trying to exploiting this.

Also, this prevents overwhelming of the device's resources.
Section 10.1.5 of DSP0236 (v1.3.1) allows configuration of
endpoints to protect its resources.

Signed-off-by: Sumanth Bhat <sumanth.bhat@linux.intel.com>
Change-Id: Id62cfab7c25b3e1ccf955f2e924844b58b4be154
diff --git a/core.c b/core.c
index 42ef405..1b7ee39 100644
--- a/core.c
+++ b/core.c
@@ -57,6 +57,7 @@
 		ROUTE_ENDPOINT,
 		ROUTE_BRIDGE,
 	}			route_policy;
+	size_t max_message_size;
 };
 
 #ifndef BUILD_ASSERT
@@ -68,6 +69,12 @@
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 #endif
 
+/* 64kb should be sufficient for a single message. Applications
+ * requiring higher sizes can override by setting max_message_size.*/
+#ifndef MCTP_MAX_MESSAGE_SIZE
+#define MCTP_MAX_MESSAGE_SIZE 65536
+#endif
+
 static int mctp_message_tx_on_bus(struct mctp_bus *bus, mctp_eid_t src,
 				  mctp_eid_t dest, void *msg, size_t msg_len);
 
@@ -195,7 +202,7 @@
 }
 
 static int mctp_msg_ctx_add_pkt(struct mctp_msg_ctx *ctx,
-		struct mctp_pktbuf *pkt)
+		struct mctp_pktbuf *pkt, size_t max_size)
 {
 	size_t len;
 
@@ -212,6 +219,11 @@
 			new_alloc_size = ctx->buf_alloc_size * 2;
 		}
 
+		/* Don't allow heap to grow beyond a limit */
+		if (new_alloc_size > max_size)
+			return -1;
+
+
 		lbuf = __mctp_realloc(ctx->buf, new_alloc_size);
 		if (lbuf) {
 			ctx->buf = lbuf;
@@ -235,10 +247,16 @@
 
 	mctp = __mctp_alloc(sizeof(*mctp));
 	memset(mctp, 0, sizeof(*mctp));
+	mctp->max_message_size = MCTP_MAX_MESSAGE_SIZE;
 
 	return mctp;
 }
 
+void mctp_set_max_message_size(struct mctp *mctp, size_t message_size)
+{
+	mctp->max_message_size = message_size;
+}
+
 void mctp_destroy(struct mctp *mctp)
 {
 	size_t i;
@@ -470,7 +488,7 @@
 					hdr->src, hdr->dest, tag);
 		}
 
-		rc = mctp_msg_ctx_add_pkt(ctx, pkt);
+		rc = mctp_msg_ctx_add_pkt(ctx, pkt, mctp->max_message_size);
 		if (rc) {
 			mctp_msg_ctx_drop(ctx);
 		} else {
@@ -494,7 +512,7 @@
 			goto out;
 		}
 
-		rc = mctp_msg_ctx_add_pkt(ctx, pkt);
+		rc = mctp_msg_ctx_add_pkt(ctx, pkt, mctp->max_message_size);
 		if (!rc)
 			mctp_rx(mctp, bus, ctx->src, ctx->dest,
 					ctx->buf, ctx->buf_size);
@@ -517,7 +535,7 @@
 			goto out;
 		}
 
-		rc = mctp_msg_ctx_add_pkt(ctx, pkt);
+		rc = mctp_msg_ctx_add_pkt(ctx, pkt, mctp->max_message_size);
 		if (rc) {
 			mctp_msg_ctx_drop(ctx);
 			goto out;
diff --git a/libmctp.h b/libmctp.h
index a8beb72..00bce29 100644
--- a/libmctp.h
+++ b/libmctp.h
@@ -65,6 +65,7 @@
 struct mctp_bus;
 
 struct mctp *mctp_init(void);
+void mctp_set_max_message_size(struct mctp *mctp, size_t message_size);
 void mctp_destroy(struct mctp *mctp);
 
 /* Register a binding to the MCTP core, and creates a bus (populating