diff options
author | Harshavardhana <harsha@harshavardhana.net> | 2014-07-29 18:50:29 -0700 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2014-08-04 18:54:53 -0700 |
commit | 6cc22537b68cb52ebc0101fca7fb232c183b00a1 (patch) | |
tree | f5a2e8c1dc3447f600fc371796b26ffebaf74640 | |
parent | 2ff46b74b25cc2e61bfe67c43b31d8f5ca88e4ac (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.c | 16 |
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; } |