HADOOP-6722. NetUtils.connect should check that it hasn't connected a socket to itself. Contributed by Todd Lipcon.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@939026 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cd85fc46dc
commit
c59b4cd966
@ -376,6 +376,9 @@ Trunk (unreleased changes)
|
||||
HADOOP-6724. IPC doesn't properly handle IOEs thrown by socket factory.
|
||||
(Todd Lipcon via tomwhite)
|
||||
|
||||
HADOOP-6722. NetUtils.connect should check that it hasn't connected a socket
|
||||
to itself. (Todd Lipcon via tomwhite)
|
||||
|
||||
Release 0.21.0 - Unreleased
|
||||
|
||||
INCOMPATIBLE CHANGES
|
||||
|
@ -26,6 +26,7 @@
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.ConnectException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
@ -367,6 +368,21 @@ public static void connect(Socket socket,
|
||||
} else {
|
||||
SocketIOWithTimeout.connect(ch, endpoint, timeout);
|
||||
}
|
||||
|
||||
// There is a very rare case allowed by the TCP specification, such that
|
||||
// if we are trying to connect to an endpoint on the local machine,
|
||||
// and we end up choosing an ephemeral port equal to the destination port,
|
||||
// we will actually end up getting connected to ourself (ie any data we
|
||||
// send just comes right back). This is only possible if the target
|
||||
// daemon is down, so we'll treat it like connection refused.
|
||||
if (socket.getLocalPort() == socket.getPort() &&
|
||||
socket.getLocalAddress().equals(socket.getInetAddress())) {
|
||||
LOG.info("Detected a loopback TCP socket, disconnecting it");
|
||||
socket.close();
|
||||
throw new ConnectException(
|
||||
"Localhost targeted connection resulted in a loopback. " +
|
||||
"No daemon is listening on the target port.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
56
src/test/core/org/apache/hadoop/net/TestNetUtils.java
Normal file
56
src/test/core/org/apache/hadoop/net/TestNetUtils.java
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.net;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
|
||||
public class TestNetUtils {
|
||||
|
||||
/**
|
||||
* Test that we can't accidentally connect back to the connecting socket due
|
||||
* to a quirk in the TCP spec.
|
||||
*
|
||||
* This is a regression test for HADOOP-6722.
|
||||
*/
|
||||
@Test
|
||||
public void testAvoidLoopbackTcpSockets() throws Exception {
|
||||
Configuration conf = new Configuration();
|
||||
|
||||
Socket socket = NetUtils.getDefaultSocketFactory(conf)
|
||||
.createSocket();
|
||||
socket.bind(new InetSocketAddress("127.0.0.1", 0));
|
||||
System.err.println("local address: " + socket.getLocalAddress());
|
||||
System.err.println("local port: " + socket.getLocalPort());
|
||||
try {
|
||||
NetUtils.connect(socket,
|
||||
new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()),
|
||||
20000);
|
||||
socket.close();
|
||||
fail("Should not have connected");
|
||||
} catch (ConnectException ce) {
|
||||
System.err.println("Got exception: " + ce);
|
||||
assertTrue(ce.getMessage().contains("resulted in a loopback"));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user