From 6cc22537b68cb52ebc0101fca7fb232c183b00a1 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 29 Jul 2014 18:50:29 -0700 Subject: socket: add boundary checks for iobuf_get2 over rpc_hdr_bytes A malformed packet can cause a OOM while peforming iobuf_get2() on a large enough packet side. Such a scenario is observed when running vulnerability tests, it would look like one of those tests perhaps based on DDOS (Denial of Service) attacks hand-crafts a RPC packet which is of a large enough size - since we do not verify the size and do not provide any boundary checks, there are secenarios where it leads to OOM. Reproducible consistently with those tests has revealed that we should be ideally be adding a boundary check. Limit such an allocation to a 1gigabyte, as it might be sufficient to handle for all variety of RPC packets. Change-Id: I5f1411dd96d6f167993d28a1718ffef2fb4e9923 Signed-off-by: Harshavardhana Reviewed-on: http://review.gluster.org/8384 Reviewed-by: Raghavendra G Tested-by: Raghavendra G --- rpc/rpc-transport/socket/src/socket.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'rpc/rpc-transport') diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index e969a5cf7fd..94b243bab15 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -847,6 +847,7 @@ __socket_reset (rpc_transport_t *this) if (priv->incoming.iobuf) { iobuf_unref (priv->incoming.iobuf); + priv->incoming.iobuf = NULL; } GF_FREE (priv->incoming.request_info); @@ -1899,10 +1900,10 @@ out: } -static inline -void __socket_reset_priv (socket_private_t *priv) +static inline void +__socket_reset_priv (socket_private_t *priv) { - struct gf_sock_incoming *in = NULL; + struct gf_sock_incoming *in = NULL; /* used to reduce the indirection */ in = &priv->incoming; @@ -1914,6 +1915,7 @@ void __socket_reset_priv (socket_private_t *priv) if (in->iobuf) { iobuf_unref (in->iobuf); + in->iobuf = NULL; } if (in->request_info != NULL) { @@ -1924,7 +1926,6 @@ void __socket_reset_priv (socket_private_t *priv) memset (&in->payload_vector, 0, sizeof (in->payload_vector)); - in->iobuf = NULL; } @@ -1987,6 +1988,12 @@ __socket_proto_state_machine (rpc_transport_t *this, in->fraghdr = ntoh32 (in->fraghdr); in->total_bytes_read += RPC_FRAGSIZE(in->fraghdr); + + if (in->total_bytes_read >= GF_UNIT_GB) { + ret = -ENOMEM; + goto out; + } + iobuf = iobuf_get2 (this->ctx->iobuf_pool, (in->total_bytes_read + sizeof (in->fraghdr))); @@ -2087,6 +2094,7 @@ out: if ((ret == -1) && (errno == EAGAIN)) { ret = 0; } + return ret; } -- cgit