8344220: Remove calls to SecurityManager and doPrivileged in java.net.InetAddress and sun.net.util.IPAddressUtil after JEP 486 integration

Reviewed-by: jpai, dfuchs, alanb
This commit is contained in:
Aleksei Efimov 2024-11-27 19:25:50 +00:00
parent 9527586923
commit 880f9a7b16
6 changed files with 87 additions and 297 deletions

View file

@ -28,8 +28,6 @@ package java.net;
import java.net.spi.InetAddressResolver;
import java.net.spi.InetAddressResolverProvider;
import java.net.spi.InetAddressResolver.LookupPolicy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
import java.util.NavigableSet;
import java.util.ArrayList;
@ -62,7 +60,6 @@ import jdk.internal.misc.Blocker;
import jdk.internal.misc.VM;
import jdk.internal.vm.annotation.Stable;
import sun.net.ResolverProviderConfiguration;
import sun.security.action.*;
import sun.net.InetAddressCachePolicy;
import sun.net.util.IPAddressUtil;
import sun.nio.cs.UTF_8;
@ -364,11 +361,11 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
*/
static {
PREFER_IPV4_STACK_VALUE =
GetPropertyAction.privilegedGetProperty("java.net.preferIPv4Stack");
System.getProperty("java.net.preferIPv4Stack");
PREFER_IPV6_ADDRESSES_VALUE =
GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
System.getProperty("java.net.preferIPv6Addresses");
HOSTS_FILE_NAME =
GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
System.getProperty("jdk.net.hosts.file");
jdk.internal.loader.BootLoader.loadLibrary("net");
SharedSecrets.setJavaNetInetAddressAccess(
new JavaNetInetAddressAccess() {
@ -440,19 +437,9 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
// Native method to check if IPv6 is available
private static native boolean isIPv6Supported();
/**
* The {@code RuntimePermission("inetAddressResolverProvider")} is
* necessary to subclass and instantiate the {@code InetAddressResolverProvider}
* class, as well as to obtain resolver from an instance of that class,
* and it is also required to obtain the operating system name resolution configurations.
*/
private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
new RuntimePermission("inetAddressResolverProvider");
private static final ReentrantLock RESOLVER_LOCK = new ReentrantLock();
private static volatile InetAddressResolver bootstrapResolver;
@SuppressWarnings("removal")
private static InetAddressResolver resolver() {
InetAddressResolver cns = resolver;
if (cns != null) {
@ -476,10 +463,6 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
if (HOSTS_FILE_NAME != null) {
// The default resolver service is already host file resolver
cns = BUILTIN_RESOLVER;
} else if (System.getSecurityManager() != null) {
PrivilegedAction<InetAddressResolver> pa = InetAddress::loadResolver;
cns = AccessController.doPrivileged(
pa, null, INET_ADDRESS_RESOLVER_PERMISSION);
} else {
cns = loadResolver();
}
@ -737,25 +720,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
* @see InetAddress#getCanonicalHostName
*/
public String getHostName() {
return getHostName(true);
}
/**
* Returns the hostname for this address.
* If the host is equal to null, then this address refers to any
* of the local machine's available network addresses.
* this is package private so SocketPermission can make calls into
* here without a security check.
*
* @return the host name for this IP address, or if the operation
* is not allowed by the security check, the textual
* representation of the IP address.
*
* @param check make security check if true
*/
String getHostName(boolean check) {
if (holder().getHostName() == null) {
holder().hostName = InetAddress.getHostFromNameService(this, check);
holder().hostName = InetAddress.getHostFromNameService(this);
}
return holder().getHostName();
}
@ -782,45 +748,31 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
String value = canonicalHostName;
if (value == null)
canonicalHostName = value =
InetAddress.getHostFromNameService(this, true);
InetAddress.getHostFromNameService(this);
return value;
}
/**
* Returns the fully qualified domain name for the given address.
*
* @param check make security check if true
*
* @return the fully qualified domain name for the given IP address.
* If either the operation is not allowed by the security check
* or the system-wide resolver wasn't able to determine the
* If the system-wide resolver wasn't able to determine the
* fully qualified domain name for the IP address, the textual
* representation of the IP address is returned instead.
*/
private static String getHostFromNameService(InetAddress addr, boolean check) {
private static String getHostFromNameService(InetAddress addr) {
String host;
var resolver = resolver();
try {
// first lookup the hostname
host = resolver.lookupByAddress(addr.getAddress());
/* check to see if calling code is allowed to know
* the hostname for this IP address, ie, connect to the host
*/
if (check) {
@SuppressWarnings("removal")
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkConnect(host, -1);
}
}
/* now get all the IP addresses for this hostname,
* and make sure one of them matches the original IP
* address. We do this to try and prevent spoofing.
*/
InetAddress[] arr = InetAddress.getAllByName0(host, check);
InetAddress[] arr = InetAddress.getAllByName0(host);
boolean ok = false;
if (arr != null) {
@ -1613,7 +1565,7 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
// and ends with square brackets, but we got something else.
throw invalidIPv6LiteralException(host, true);
}
return getAllByName0(host, true, true);
return getAllByName0(host, true);
}
private static UnknownHostException invalidIPv6LiteralException(String host, boolean wrapInBrackets) {
@ -1639,9 +1591,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
/**
* package private so SocketPermission can call it
*/
static InetAddress[] getAllByName0 (String host, boolean check)
throws UnknownHostException {
return getAllByName0(host, check, true);
static InetAddress[] getAllByName0(String host) throws UnknownHostException {
return getAllByName0(host, true);
}
/**
@ -1682,30 +1633,16 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
* Designated lookup method.
*
* @param host host name to look up
* @param check perform security check
* @param useCache use cached value if not expired else always
* perform name service lookup (and cache the result)
* @return array of InetAddress(es)
* @throws UnknownHostException if host name is not found
*/
private static InetAddress[] getAllByName0(String host,
boolean check,
boolean useCache)
throws UnknownHostException {
/* If it gets here it is presumed to be a hostname */
/* make sure the connection to the host is allowed, before we
* give out a hostname
*/
if (check) {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkConnect(host, -1);
}
}
// remove expired addresses from cache - expirySet keeps them ordered
// by expiry time so we only need to iterate the prefix of the NavigableSet...
long now = System.nanoTime();
@ -1822,48 +1759,33 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
* @see java.net.InetAddress#getByName(java.lang.String)
*/
public static InetAddress getLocalHost() throws UnknownHostException {
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
try {
// is cached data still valid?
CachedLocalHost clh = cachedLocalHost;
if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
if (security != null) {
security.checkConnect(clh.host, -1);
}
return clh.addr;
}
String local = impl.getLocalHostName();
if (security != null) {
security.checkConnect(local, -1);
}
InetAddress localAddr;
if (local.equals("localhost")) {
// shortcut for "localhost" host name
localAddr = impl.loopbackAddress();
} else {
// call getAllByName0 without security checks and
// without using cached data
try {
localAddr = getAllByName0(local, false, false)[0];
} catch (UnknownHostException uhe) {
// Rethrow with a more informative error message.
UnknownHostException uhe2 =
new UnknownHostException(local + ": " +
uhe.getMessage());
uhe2.initCause(uhe);
throw uhe2;
}
}
cachedLocalHost = new CachedLocalHost(local, localAddr);
return localAddr;
} catch (java.lang.SecurityException e) {
return impl.loopbackAddress();
// is cached data still valid?
CachedLocalHost clh = cachedLocalHost;
if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
return clh.addr;
}
String local = impl.getLocalHostName();
InetAddress localAddr;
if (local.equals("localhost")) {
// shortcut for "localhost" host name
localAddr = impl.loopbackAddress();
} else {
// call getAllByName0 without using cached data
try {
localAddr = getAllByName0(local, false)[0];
} catch (UnknownHostException uhe) {
// Rethrow with a more informative error message.
UnknownHostException uhe2 =
new UnknownHostException(local + ": " +
uhe.getMessage());
uhe2.initCause(uhe);
throw uhe2;
}
}
cachedLocalHost = new CachedLocalHost(local, localAddr);
return localAddr;
}
/**

View file

@ -30,10 +30,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.security.AccessController;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
@ -638,10 +636,10 @@ public final class SocketPermission extends Permission
// we have to do this check, otherwise we might not
// get the fully qualified domain name
if (init_with_ip) {
cname = addresses[0].getHostName(false).toLowerCase(Locale.ROOT);
cname = addresses[0].getHostName().toLowerCase(Locale.ROOT);
} else {
cname = InetAddress.getByName(addresses[0].getHostAddress()).
getHostName(false).toLowerCase(Locale.ROOT);
getHostName().toLowerCase(Locale.ROOT);
}
} catch (UnknownHostException uhe) {
invalid = true;
@ -705,7 +703,7 @@ public final class SocketPermission extends Permission
// Following check seems unnecessary
// auth = InetAddress.getAllByName0(authHost, false)[0];
authHost = hostname + '.' + authHost;
auth = InetAddress.getAllByName0(authHost, false)[0];
auth = InetAddress.getAllByName0(authHost)[0];
if (auth.equals(InetAddress.getByAddress(addr))) {
return true;
}
@ -736,9 +734,8 @@ public final class SocketPermission extends Permission
sb.append('.');
}
authHost = "auth." + sb.toString() + "IP6.ARPA";
//auth = InetAddress.getAllByName0(authHost, false)[0];
authHost = hostname + '.' + authHost;
auth = InetAddress.getAllByName0(authHost, false)[0];
auth = InetAddress.getAllByName0(authHost)[0];
if (auth.equals(InetAddress.getByAddress(addr)))
return true;
Debug debug = getDebug();
@ -780,7 +777,7 @@ public final class SocketPermission extends Permission
}
addresses =
new InetAddress[] {InetAddress.getAllByName0(host, false)[0]};
new InetAddress[] {InetAddress.getAllByName0(host)[0]};
} catch (UnknownHostException uhe) {
invalid = true;
@ -1191,23 +1188,15 @@ public final class SocketPermission extends Permission
* Check the system/security property for the ephemeral port range
* for this system. The suffix is either "high" or "low"
*/
@SuppressWarnings("removal")
private static int initEphemeralPorts(String suffix) {
return AccessController.doPrivileged(
new PrivilegedAction<>(){
public Integer run() {
int val = Integer.getInteger(
"jdk.net.ephemeralPortRange."+suffix, -1
);
if (val != -1) {
return val;
} else {
return suffix.equals("low") ?
PortConfig.getLower() : PortConfig.getUpper();
}
}
}
);
int val = Integer.getInteger(
"jdk.net.ephemeralPortRange." + suffix, -1);
if (val != -1) {
return val;
} else {
return suffix.equals("low") ?
PortConfig.getLower() : PortConfig.getUpper();
}
}
/**

View file

@ -279,8 +279,7 @@ tuning on how the cache is operating.</P>
name lookups will be kept in the cache. A value of -1, or any other
negative value for that matter, indicates a &ldquo;cache forever&rdquo;
policy, while a value of 0 (zero) means no caching. The default value
is -1 (forever) if a security manager is installed, and implementation-specific
when no security manager is installed.</P>
is implementation-specific.</P>
<LI><P><B>{@code networkaddress.cache.stale.ttl}</B> (default: see below)<BR>
Value is an integer corresponding to the number of seconds that stale names
will be kept in the cache. A name is considered stale if the TTL has expired

View file

@ -98,15 +98,6 @@ public abstract class InetAddressResolverProvider {
*/
public abstract String name();
/**
* The {@code RuntimePermission("inetAddressResolverProvider")} is
* necessary to subclass and instantiate the {@code InetAddressResolverProvider} class,
* as well as to obtain resolver from an instance of that class,
* and it is also required to obtain the operating system name resolution configurations.
*/
private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
new RuntimePermission("inetAddressResolverProvider");
/**
* Creates a new instance of {@code InetAddressResolverProvider}.
*
@ -116,19 +107,6 @@ public abstract class InetAddressResolverProvider {
* service provider.
*/
protected InetAddressResolverProvider() {
this(checkPermission());
}
private InetAddressResolverProvider(Void unused) {
}
@SuppressWarnings("removal")
private static Void checkPermission() {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(INET_ADDRESS_RESOLVER_PERMISSION);
}
return null;
}
/**