summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarshavardhana <harsha@harshavardhana.net>2014-07-29 18:50:29 -0700
committerRaghavendra G <rgowdapp@redhat.com>2014-08-04 18:54:53 -0700
commit6cc22537b68cb52ebc0101fca7fb232c183b00a1 (patch)
treef5a2e8c1dc3447f600fc371796b26ffebaf74640
parent2ff46b74b25cc2e61bfe67c43b31d8f5ca88e4ac (diff)
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 <harsha@harshavardhana.net> Reviewed-on: http://review.gluster.org/8384 Reviewed-by: Raghavendra G <rgowdapp@redhat.com> Tested-by: Raghavendra G <rgowdapp@redhat.com>
-rw-r--r--rpc/rpc-transport/socket/src/socket.c16
1 files changed, 12 insertions, 4 deletions
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;
}