From a4246c2da658d9b5b02a4caba511688748a88b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Thu, 14 May 2015 15:24:18 +0300 Subject: eth, eth/downloader: handle a potential unknown parent attack --- eth/sync.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'eth/sync.go') diff --git a/eth/sync.go b/eth/sync.go index 00b571782..b51fb7c10 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -2,6 +2,7 @@ package eth import ( "math" + "sync/atomic" "time" "github.com/ethereum/go-ethereum/eth/downloader" @@ -14,6 +15,7 @@ import ( func (pm *ProtocolManager) update() { forceSync := time.Tick(forceSyncCycle) blockProc := time.Tick(blockProcCycle) + blockProcPend := int32(0) for { select { @@ -36,7 +38,14 @@ func (pm *ProtocolManager) update() { } case <-blockProc: // Try to pull some blocks from the downloaded - go pm.processBlocks() + if atomic.CompareAndSwapInt32(&blockProcPend, 0, 1) { + go func() { + if err := pm.processBlocks(); err != nil { + pm.downloader.Cancel() + } + atomic.StoreInt32(&blockProcPend, 0) + }() + } case <-pm.quitSync: return @@ -52,8 +61,12 @@ func (pm *ProtocolManager) processBlocks() error { pm.wg.Add(1) defer pm.wg.Done() - // Take a batch of blocks (will return nil if a previous batch has not reached the chain yet) - blocks := pm.downloader.TakeBlocks() + // Take a batch of blocks, but abort if there's an invalid head or if the chain's empty + blocks, err := pm.downloader.TakeBlocks() + if err != nil { + glog.V(logger.Warn).Infof("Block processing failed: %v", err) + return err + } if len(blocks) == 0 { return nil } @@ -63,9 +76,7 @@ func (pm *ProtocolManager) processBlocks() error { max := int(math.Min(float64(len(blocks)), float64(blockProcAmount))) _, err := pm.chainman.InsertChain(blocks[:max]) if err != nil { - // cancel download process - pm.downloader.Cancel() - + glog.V(logger.Warn).Infof("Block insertion failed: %v", err) return err } blocks = blocks[max:] -- cgit v1.2.3 From 3eda70c64c3b790573751227f8ac0fe42bdc0307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Thu, 14 May 2015 15:38:49 +0300 Subject: eth, eth/downloader: remove parent verification from the downlaoder --- eth/sync.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'eth/sync.go') diff --git a/eth/sync.go b/eth/sync.go index b51fb7c10..c89f34596 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -40,9 +40,7 @@ func (pm *ProtocolManager) update() { // Try to pull some blocks from the downloaded if atomic.CompareAndSwapInt32(&blockProcPend, 0, 1) { go func() { - if err := pm.processBlocks(); err != nil { - pm.downloader.Cancel() - } + pm.processBlocks() atomic.StoreInt32(&blockProcPend, 0) }() } @@ -61,12 +59,8 @@ func (pm *ProtocolManager) processBlocks() error { pm.wg.Add(1) defer pm.wg.Done() - // Take a batch of blocks, but abort if there's an invalid head or if the chain's empty - blocks, err := pm.downloader.TakeBlocks() - if err != nil { - glog.V(logger.Warn).Infof("Block processing failed: %v", err) - return err - } + // Short circuit if no blocks are available for insertion + blocks := pm.downloader.TakeBlocks() if len(blocks) == 0 { return nil } @@ -77,6 +71,7 @@ func (pm *ProtocolManager) processBlocks() error { _, err := pm.chainman.InsertChain(blocks[:max]) if err != nil { glog.V(logger.Warn).Infof("Block insertion failed: %v", err) + pm.downloader.Cancel() return err } blocks = blocks[max:] -- cgit v1.2.3 From cd2fb0905109828028172c84f9c10f1343647ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 15 May 2015 01:40:16 +0300 Subject: eth, eth/downloader: prevent hash repeater attack --- eth/sync.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'eth/sync.go') diff --git a/eth/sync.go b/eth/sync.go index c89f34596..73f6253be 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -101,11 +101,13 @@ func (pm *ProtocolManager) synchronise(peer *peer) { case downloader.ErrBusy: glog.V(logger.Debug).Infof("Synchronisation already in progress") - case downloader.ErrTimeout: - glog.V(logger.Debug).Infof("Removing peer %v due to sync timeout", peer.id) + case downloader.ErrTimeout, downloader.ErrBadPeer: + glog.V(logger.Debug).Infof("Removing peer %v: %v", peer.id, err) pm.removePeer(peer) + case downloader.ErrPendingQueue: glog.V(logger.Debug).Infoln("Synchronisation aborted:", err) + default: glog.V(logger.Warn).Infof("Synchronisation failed: %v", err) } -- cgit v1.2.3 From 9ad515d2dc62c5d1ce1099efa89bd0a0b3f06a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 15 May 2015 12:01:05 +0300 Subject: eth: drop a sync peer if it sends an invalid hash chain --- eth/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eth/sync.go') diff --git a/eth/sync.go b/eth/sync.go index 73f6253be..cc1fe80ea 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -101,7 +101,7 @@ func (pm *ProtocolManager) synchronise(peer *peer) { case downloader.ErrBusy: glog.V(logger.Debug).Infof("Synchronisation already in progress") - case downloader.ErrTimeout, downloader.ErrBadPeer: + case downloader.ErrTimeout, downloader.ErrBadPeer, downloader.ErrInvalidChain: glog.V(logger.Debug).Infof("Removing peer %v: %v", peer.id, err) pm.removePeer(peer) -- cgit v1.2.3 From 83226762c20dbf48939d76046ad32422a44feda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 15 May 2015 13:14:46 +0300 Subject: eth, eth/downloader: detect and handle madeup hash attacks --- eth/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eth/sync.go') diff --git a/eth/sync.go b/eth/sync.go index cc1fe80ea..aa7ebc77b 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -101,7 +101,7 @@ func (pm *ProtocolManager) synchronise(peer *peer) { case downloader.ErrBusy: glog.V(logger.Debug).Infof("Synchronisation already in progress") - case downloader.ErrTimeout, downloader.ErrBadPeer, downloader.ErrInvalidChain: + case downloader.ErrTimeout, downloader.ErrBadPeer, downloader.ErrInvalidChain, downloader.ErrCrossCheckFailed: glog.V(logger.Debug).Infof("Removing peer %v: %v", peer.id, err) pm.removePeer(peer) -- cgit v1.2.3