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.
|
HADOOP-6724. IPC doesn't properly handle IOEs thrown by socket factory.
|
||||||
(Todd Lipcon via tomwhite)
|
(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
|
Release 0.21.0 - Unreleased
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.net.ConnectException;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -367,6 +368,21 @@ public static void connect(Socket socket,
|
|||||||
} else {
|
} else {
|
||||||
SocketIOWithTimeout.connect(ch, endpoint, timeout);
|
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