aboutsummaryrefslogtreecommitdiffstats
path: root/eth
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2015-07-01 20:19:11 +0800
committerPéter Szilágyi <peterke@gmail.com>2015-07-01 20:21:35 +0800
commitd6f2c0a76f6635ebeb245815c5f686c545ed527d (patch)
tree4de6598a2f8df2086b5b3892f25750757aeeede6 /eth
parent1ae80aaf64c5acfde19fee5ee3bc4579db7ea76e (diff)
downloaddexon-d6f2c0a76f6635ebeb245815c5f686c545ed527d.tar.gz
dexon-d6f2c0a76f6635ebeb245815c5f686c545ed527d.tar.zst
dexon-d6f2c0a76f6635ebeb245815c5f686c545ed527d.zip
eth, eth/downloader: fix #1231, DOS vulnerability in hash queueing
Diffstat (limited to 'eth')
-rw-r--r--eth/downloader/downloader.go18
-rw-r--r--eth/handler.go2
2 files changed, 15 insertions, 5 deletions
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index ce85aec17..c788048e9 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -34,8 +34,9 @@ var (
blockHardTTL = 3 * blockSoftTTL // Maximum time allowance before a block request is considered expired
crossCheckCycle = time.Second // Period after which to check for expired cross checks
- maxBannedHashes = 4096 // Number of bannable hashes before phasing old ones out
- maxBlockProcess = 256 // Number of blocks to import at once into the chain
+ maxQueuedHashes = 256 * 1024 // Maximum number of hashes to queue for import (DOS protection)
+ maxBannedHashes = 4096 // Number of bannable hashes before phasing old ones out
+ maxBlockProcess = 256 // Number of blocks to import at once into the chain
)
var (
@@ -780,6 +781,8 @@ func (d *Downloader) fetchHashes(p *peer, from uint64) error {
defer timeout.Stop()
getHashes := func(from uint64) {
+ glog.V(logger.Detail).Infof("%v: fetching %d hashes from #%d", p, MaxHashFetch, from)
+
go p.getAbsHashes(from, MaxHashFetch)
timeout.Reset(hashTTL)
}
@@ -809,16 +812,23 @@ func (d *Downloader) fetchHashes(p *peer, from uint64) error {
return nil
}
// Otherwise insert all the new hashes, aborting in case of junk
+ glog.V(logger.Detail).Infof("%v: inserting %d hashes from #%d", p, len(hashPack.hashes), from)
+
inserts := d.queue.Insert(hashPack.hashes, true)
if len(inserts) != len(hashPack.hashes) {
glog.V(logger.Debug).Infof("%v: stale hashes", p)
return errBadPeer
}
- // Notify the block fetcher of new hashes, and continue fetching
+ // Notify the block fetcher of new hashes, but stop if queue is full
+ cont := d.queue.Pending() < maxQueuedHashes
select {
- case d.processCh <- true:
+ case d.processCh <- cont:
default:
}
+ if !cont {
+ return nil
+ }
+ // Queue not yet full, fetch the next batch
from += uint64(len(hashPack.hashes))
getHashes(from)
diff --git a/eth/handler.go b/eth/handler.go
index 86e8a325f..59bbb480b 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -164,7 +164,7 @@ func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter
// handle is the callback invoked to manage the life cycle of an eth peer. When
// this function terminates, the peer is disconnected.
func (pm *ProtocolManager) handle(p *peer) error {
- glog.V(logger.Debug).Infof("%v: peer connected", p)
+ glog.V(logger.Debug).Infof("%v: peer connected [%s]", p, p.Name())
// Execute the Ethereum handshake
td, head, genesis := pm.chainman.Status()