From 880f9a7b161fc5092ece8cfe02b5c55c32baba36 Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Wed, 27 Nov 2024 19:25:50 +0000 Subject: [PATCH] 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 --- .../share/classes/java/net/InetAddress.java | 152 +++++------------- .../classes/java/net/SocketPermission.java | 37 ++--- .../java/net/doc-files/net-properties.html | 3 +- .../net/spi/InetAddressResolverProvider.java | 22 --- .../sun/net/InetAddressCachePolicy.java | 138 +++------------- .../classes/sun/net/util/IPAddressUtil.java | 32 ++-- 6 files changed, 87 insertions(+), 297 deletions(-) diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index 746ce04e8a2..e94df5a9e0a 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -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 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; } /** diff --git a/src/java.base/share/classes/java/net/SocketPermission.java b/src/java.base/share/classes/java/net/SocketPermission.java index 0a2b586f7c1..0c49e6cafef 100644 --- a/src/java.base/share/classes/java/net/SocketPermission.java +++ b/src/java.base/share/classes/java/net/SocketPermission.java @@ -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(); + } } /** diff --git a/src/java.base/share/classes/java/net/doc-files/net-properties.html b/src/java.base/share/classes/java/net/doc-files/net-properties.html index a67df0c0d00..684c90a8164 100644 --- a/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -279,8 +279,7 @@ tuning on how the cache is operating.

name lookups will be kept in the cache. A value of -1, or any other negative value for that matter, indicates a “cache forever” 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.

+ is implementation-specific.

  • {@code networkaddress.cache.stale.ttl} (default: see below)
    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 diff --git a/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java b/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java index 5b032591089..a5dbc938cc2 100644 --- a/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java +++ b/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java @@ -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; } /** diff --git a/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java b/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java index 5c127025682..0cce06ae137 100644 --- a/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java +++ b/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,8 @@ package sun.net; -import java.security.PrivilegedAction; import java.security.Security; -import java.util.concurrent.TimeUnit; -@SuppressWarnings("removal") public final class InetAddressCachePolicy { // Controls the cache policy for successful lookups only @@ -60,11 +57,9 @@ public final class InetAddressCachePolicy { * -1: caching forever * any positive value: the number of seconds to cache an address for * - * default value is forever (FOREVER), as we let the platform do the - * caching. For security reasons, this caching is made forever when - * a security manager is set. + * default value is 30 seconds */ - private static volatile int cachePolicy = FOREVER; + private static volatile int cachePolicy = DEFAULT_POSITIVE; /* The Java-level namelookup cache stale policy: * @@ -85,40 +80,22 @@ public final class InetAddressCachePolicy { */ private static volatile int negativeCachePolicy = NEVER; - /* - * Whether or not the cache policy for successful lookups was set - * using a property (cmd line). - */ - private static boolean propertySet; - - /* - * Whether or not the cache policy for negative lookups was set - * using a property (cmd line). - */ - private static boolean propertyNegativeSet; - /* * Initialize */ static { + /* If the cache policy property is not specified + * then the default positive cache value is used. + */ Integer tmp = getProperty(cachePolicyProp, cachePolicyPropFallback); if (tmp != null) { cachePolicy = tmp < 0 ? FOREVER : tmp; - propertySet = true; - } else { - /* No properties defined for positive caching. If there is no - * security manager then use the default positive cache value. - */ - if (System.getSecurityManager() == null) { - cachePolicy = DEFAULT_POSITIVE; - } } tmp = getProperty(negativeCachePolicyProp, negativeCachePolicyPropFallback); if (tmp != null) { negativeCachePolicy = tmp < 0 ? FOREVER : tmp; - propertyNegativeSet = true; } if (cachePolicy > 0) { tmp = getProperty(cacheStalePolicyProp, @@ -130,33 +107,25 @@ public final class InetAddressCachePolicy { } private static Integer getProperty(String cachePolicyProp, - String cachePolicyPropFallback) - { - return java.security.AccessController.doPrivileged( - new PrivilegedAction() { - public Integer run() { - try { - String tmpString = Security.getProperty( - cachePolicyProp); - if (tmpString != null) { - return Integer.valueOf(tmpString); - } - } catch (NumberFormatException ignored) { - // Ignore - } + String cachePolicyPropFallback) { + try { + String tmpString = Security.getProperty(cachePolicyProp); + if (tmpString != null) { + return Integer.valueOf(tmpString); + } + } catch (NumberFormatException ignored) { + // Ignore + } - try { - String tmpString = System.getProperty( - cachePolicyPropFallback); - if (tmpString != null) { - return Integer.decode(tmpString); - } - } catch (NumberFormatException ignored) { - // Ignore - } - return null; - } - }); + try { + String tmpString = System.getProperty(cachePolicyPropFallback); + if (tmpString != null) { + return Integer.decode(tmpString); + } + } catch (NumberFormatException ignored) { + // Ignore + } + return null; } public static int get() { @@ -170,63 +139,4 @@ public final class InetAddressCachePolicy { public static int getNegative() { return negativeCachePolicy; } - - /** - * Sets the cache policy for successful lookups if the user has not - * already specified a cache policy for it using a - * command-property. - * @param newPolicy the value in seconds for how long the lookup - * should be cached - */ - public static synchronized void setIfNotSet(int newPolicy) { - /* - * When setting the new value we may want to signal that the - * cache should be flushed, though this doesn't seem strictly - * necessary. - */ - if (!propertySet) { - checkValue(newPolicy, cachePolicy); - cachePolicy = newPolicy; - } - } - - /** - * Sets the cache policy for negative lookups if the user has not - * already specified a cache policy for it using a - * command-property. - * @param newPolicy the value in seconds for how long the lookup - * should be cached - */ - public static void setNegativeIfNotSet(int newPolicy) { - /* - * When setting the new value we may want to signal that the - * cache should be flushed, though this doesn't seem strictly - * necessary. - */ - if (!propertyNegativeSet) { - // Negative caching does not seem to have any security - // implications. - // checkValue(newPolicy, negativeCachePolicy); - // but we should normalize negative policy - negativeCachePolicy = newPolicy < 0 ? FOREVER : newPolicy; - } - } - - private static void checkValue(int newPolicy, int oldPolicy) { - /* - * If malicious code gets a hold of this method, prevent - * setting the cache policy to something laxer or some - * invalid negative value. - */ - if (newPolicy == FOREVER) - return; - - if ((oldPolicy == FOREVER) || - (newPolicy < oldPolicy) || - (newPolicy < FOREVER)) { - - throw new - SecurityException("can't make InetAddress cache more lax"); - } - } } diff --git a/src/java.base/share/classes/sun/net/util/IPAddressUtil.java b/src/java.base/share/classes/sun/net/util/IPAddressUtil.java index ecd60a9ffc4..b3da295c4a7 100644 --- a/src/java.base/share/classes/sun/net/util/IPAddressUtil.java +++ b/src/java.base/share/classes/sun/net/util/IPAddressUtil.java @@ -25,8 +25,6 @@ package sun.net.util; -import sun.security.action.GetPropertyAction; - import java.io.UncheckedIOException; import java.net.Inet6Address; import java.net.InetAddress; @@ -35,9 +33,6 @@ import java.net.NetworkInterface; import java.net.SocketException; import java.net.URL; import java.nio.CharBuffer; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; import java.util.Arrays; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -396,25 +391,23 @@ public class IPAddressUtil { } } - @SuppressWarnings("removal") private static InetAddress findScopedAddress(InetAddress address) { - PrivilegedExceptionAction> pa = () -> NetworkInterface.networkInterfaces() - .flatMap(NetworkInterface::inetAddresses) - .filter(a -> (a instanceof Inet6Address) - && address.equals(a) - && ((Inet6Address) a).getScopeId() != 0) - .toList(); - List result; try { - result = AccessController.doPrivileged(pa); + List result = NetworkInterface.networkInterfaces() + .flatMap(NetworkInterface::inetAddresses) + .filter(a -> (a instanceof Inet6Address) + && address.equals(a) + && ((Inet6Address) a).getScopeId() != 0) + .toList(); + var sz = result.size(); if (sz == 0) return null; if (sz > 1) throw new UncheckedIOException(new SocketException( - "Duplicate link local addresses: must specify scope-id")); + "Duplicate link local addresses: must specify scope-id")); return result.get(0); - } catch (PrivilegedActionException pae) { + } catch (SocketException socketException) { return null; } } @@ -927,8 +920,8 @@ public class IPAddressUtil { private static final long TERMINAL_PARSE_ERROR = -2L; private static final String ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP = "jdk.net.allowAmbiguousIPAddressLiterals"; - private static final boolean ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE = Boolean.valueOf( - GetPropertyAction.privilegedGetProperty(ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP, "false")); + private static final boolean ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE = + Boolean.getBoolean(ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP); private static class MASKS { private static final String DELAY_URL_PARSING_SP = "jdk.net.url.delayParsing"; private static final boolean DELAY_URL_PARSING_SP_VALUE; @@ -939,8 +932,7 @@ public class IPAddressUtil { static final long L_SCOPE_MASK; static final long H_SCOPE_MASK; static { - var value = GetPropertyAction.privilegedGetProperty( - DELAY_URL_PARSING_SP, "false"); + var value = System.getProperty(DELAY_URL_PARSING_SP, "false"); DELAY_URL_PARSING_SP_VALUE = value.isEmpty() || Boolean.parseBoolean(value); if (DELAY_URL_PARSING_SP_VALUE) {