Skip to content

Commit 31a36e0

Browse files
author
Norman Maurer
committed
[netty#2353] Use a privileged block to get ClassLoader and System property if needed
Motivation: When using System.getProperty(...) and various methods to get a ClassLoader it will fail when a SecurityManager is in place. Modifications: Use a priveled block if needed. This work is based in the PR netty#2353 done by @anilsaldhana . Result: Code works also when SecurityManager is present
1 parent 6982663 commit 31a36e0

File tree

15 files changed

+111
-29
lines changed

15 files changed

+111
-29
lines changed

codec/src/main/java/io/netty/handler/codec/serialization/ClassResolvers.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ static ClassLoader defaultClassLoader(ClassLoader classLoader) {
9090
return classLoader;
9191
}
9292

93-
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
93+
final ClassLoader contextClassLoader = PlatformDependent.getContextClassLoader();
9494
if (contextClassLoader != null) {
9595
return contextClassLoader;
9696
}
9797

98-
return ClassResolvers.class.getClassLoader();
98+
return PlatformDependent.getClassLoader(ClassResolvers.class);
9999
}
100100

101101
private ClassResolvers() {

common/src/main/java/io/netty/util/Version.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package io.netty.util;
1818

19+
import io.netty.util.internal.PlatformDependent;
20+
1921
import java.io.InputStream;
2022
import java.net.URL;
2123
import java.text.ParseException;
@@ -61,7 +63,7 @@ public static Map<String, Version> identify() {
6163
*/
6264
public static Map<String, Version> identify(ClassLoader classLoader) {
6365
if (classLoader == null) {
64-
classLoader = Thread.currentThread().getContextClassLoader();
66+
classLoader = PlatformDependent.getContextClassLoader();
6567
}
6668

6769
// Collect all properties.

common/src/main/java/io/netty/util/internal/JavassistTypeParameterMatcherGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ public static ClassPool classPool() {
5151
}
5252

5353
public static TypeParameterMatcher generate(Class<?> type) {
54-
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
54+
ClassLoader classLoader = PlatformDependent.getContextClassLoader();
5555
if (classLoader == null) {
56-
classLoader = ClassLoader.getSystemClassLoader();
56+
classLoader = PlatformDependent.getSystemClassLoader();
5757
}
5858
return generate(type, classLoader);
5959
}

common/src/main/java/io/netty/util/internal/PlatformDependent.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,31 @@ public static Queue<Runnable> newMpscQueue() {
387387
}
388388
}
389389

390+
/**
391+
* Return the {@link ClassLoader} for the given {@link Class}.
392+
*/
393+
public static ClassLoader getClassLoader(final Class<?> clazz) {
394+
return PlatformDependent0.getClassLoader(clazz);
395+
}
396+
397+
/**
398+
* Return the context {@link ClassLoader} for the current {@link Thread}.
399+
*/
400+
public static ClassLoader getContextClassLoader() {
401+
return PlatformDependent0.getContextClassLoader();
402+
}
403+
404+
/**
405+
* Return the system {@link ClassLoader}.
406+
*/
407+
public static ClassLoader getSystemClassLoader() {
408+
return PlatformDependent0.getSystemClassLoader();
409+
}
410+
390411
private static boolean isAndroid0() {
391412
boolean android;
392413
try {
393-
Class.forName("android.app.Application", false, ClassLoader.getSystemClassLoader());
414+
Class.forName("android.app.Application", false, getSystemClassLoader());
394415
android = true;
395416
} catch (Exception e) {
396417
// Failed to load the class uniquely available in Android.
@@ -517,15 +538,15 @@ private static int javaVersion0() {
517538
}
518539

519540
try {
520-
Class.forName("java.time.Clock", false, Object.class.getClassLoader());
541+
Class.forName("java.time.Clock", false, getClassLoader(Object.class));
521542
javaVersion = 8;
522543
break;
523544
} catch (Exception e) {
524545
// Ignore
525546
}
526547

527548
try {
528-
Class.forName("java.util.concurrent.LinkedTransferQueue", false, BlockingQueue.class.getClassLoader());
549+
Class.forName("java.util.concurrent.LinkedTransferQueue", false, getClassLoader(BlockingQueue.class));
529550
javaVersion = 7;
530551
break;
531552
} catch (Exception e) {
@@ -591,7 +612,7 @@ private static long maxDirectMemory0() {
591612
long maxDirectMemory = 0;
592613
try {
593614
// Try to get from sun.misc.VM.maxDirectMemory() which should be most accurate.
594-
Class<?> vmClass = Class.forName("sun.misc.VM", true, ClassLoader.getSystemClassLoader());
615+
Class<?> vmClass = Class.forName("sun.misc.VM", true, getSystemClassLoader());
595616
Method m = vmClass.getDeclaredMethod("maxDirectMemory");
596617
maxDirectMemory = ((Number) m.invoke(null)).longValue();
597618
} catch (Throwable t) {
@@ -606,9 +627,9 @@ private static long maxDirectMemory0() {
606627
// Now try to get the JVM option (-XX:MaxDirectMemorySize) and parse it.
607628
// Note that we are using reflection because Android doesn't have these classes.
608629
Class<?> mgmtFactoryClass = Class.forName(
609-
"java.lang.management.ManagementFactory", true, ClassLoader.getSystemClassLoader());
630+
"java.lang.management.ManagementFactory", true, getSystemClassLoader());
610631
Class<?> runtimeClass = Class.forName(
611-
"java.lang.management.RuntimeMXBean", true, ClassLoader.getSystemClassLoader());
632+
"java.lang.management.RuntimeMXBean", true, getSystemClassLoader());
612633

613634
Object runtime = mgmtFactoryClass.getDeclaredMethod("getRuntimeMXBean").invoke(null);
614635

@@ -662,7 +683,7 @@ private static boolean hasJavassist0() {
662683
}
663684

664685
try {
665-
JavassistTypeParameterMatcherGenerator.generate(Object.class, PlatformDependent.class.getClassLoader());
686+
JavassistTypeParameterMatcherGenerator.generate(Object.class, getClassLoader(PlatformDependent.class));
666687
logger.debug("Javassist: available");
667688
return true;
668689
} catch (Throwable t) {

common/src/main/java/io/netty/util/internal/PlatformDependent0.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.nio.Buffer;
2727
import java.nio.ByteBuffer;
2828
import java.nio.ByteOrder;
29+
import java.security.AccessController;
30+
import java.security.PrivilegedAction;
2931
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
3032
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
3133
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@@ -50,7 +52,7 @@ final class PlatformDependent0 {
5052
static {
5153
boolean directBufferFreeable = false;
5254
try {
53-
Class<?> cls = Class.forName("sun.nio.ch.DirectBuffer", false, PlatformDependent0.class.getClassLoader());
55+
Class<?> cls = Class.forName("sun.nio.ch.DirectBuffer", false, getClassLoader(PlatformDependent0.class));
5456
Method method = cls.getMethod("cleaner");
5557
if ("sun.misc.Cleaner".equals(method.getReturnType().getName())) {
5658
directBufferFreeable = true;
@@ -328,6 +330,45 @@ static <T> AtomicLongFieldUpdater<T> newAtomicLongFieldUpdater(
328330
return new UnsafeAtomicLongFieldUpdater<T>(UNSAFE, tclass, fieldName);
329331
}
330332

333+
static ClassLoader getClassLoader(final Class<?> clazz) {
334+
if (System.getSecurityManager() == null) {
335+
return clazz.getClassLoader();
336+
} else {
337+
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
338+
@Override
339+
public ClassLoader run() {
340+
return clazz.getClassLoader();
341+
}
342+
});
343+
}
344+
}
345+
346+
static ClassLoader getContextClassLoader() {
347+
if (System.getSecurityManager() == null) {
348+
return Thread.currentThread().getContextClassLoader();
349+
} else {
350+
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
351+
@Override
352+
public ClassLoader run() {
353+
return Thread.currentThread().getContextClassLoader();
354+
}
355+
});
356+
}
357+
}
358+
359+
static ClassLoader getSystemClassLoader() {
360+
if (System.getSecurityManager() == null) {
361+
return ClassLoader.getSystemClassLoader();
362+
} else {
363+
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
364+
@Override
365+
public ClassLoader run() {
366+
return ClassLoader.getSystemClassLoader();
367+
}
368+
});
369+
}
370+
}
371+
331372
private PlatformDependent0() {
332373
}
333374

common/src/main/java/io/netty/util/internal/SystemPropertyUtil.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import io.netty.util.internal.logging.InternalLogger;
1919
import io.netty.util.internal.logging.InternalLoggerFactory;
2020

21+
import java.security.AccessController;
22+
import java.security.PrivilegedAction;
2123
import java.util.logging.Level;
2224
import java.util.logging.Logger;
2325
import java.util.regex.Pattern;
@@ -64,7 +66,7 @@ public static String get(String key) {
6466
* {@code def} if there's no such property or if an access to the
6567
* specified property is not allowed.
6668
*/
67-
public static String get(String key, String def) {
69+
public static String get(final String key, String def) {
6870
if (key == null) {
6971
throw new NullPointerException("key");
7072
}
@@ -74,7 +76,16 @@ public static String get(String key, String def) {
7476

7577
String value = null;
7678
try {
77-
value = System.getProperty(key);
79+
if (System.getSecurityManager() == null) {
80+
value = System.getProperty(key);
81+
} else {
82+
value = AccessController.doPrivileged(new PrivilegedAction<String>() {
83+
@Override
84+
public String run() {
85+
return System.getProperty(key);
86+
}
87+
});
88+
}
7889
} catch (Exception e) {
7990
if (!loggedException) {
8091
log("Unable to retrieve a system property '" + key + "'; default values will be used.", e);

example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import io.netty.handler.codec.http.LastHttpContent;
3535
import io.netty.handler.stream.ChunkedFile;
3636
import io.netty.util.CharsetUtil;
37+
import io.netty.util.internal.SystemPropertyUtil;
3738

3839
import javax.activation.MimetypesFileTypeMap;
3940
import java.io.File;
@@ -264,7 +265,7 @@ private static String sanitizeUri(String uri) {
264265
}
265266

266267
// Convert to absolute path.
267-
return System.getProperty("user.dir") + File.separator + uri;
268+
return SystemPropertyUtil.get("user.dir") + File.separator + uri;
268269
}
269270

270271
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");

example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.netty.channel.EventLoopGroup;
2121
import io.netty.channel.nio.NioEventLoopGroup;
2222
import io.netty.channel.socket.nio.NioServerSocketChannel;
23+
import io.netty.util.internal.SystemPropertyUtil;
2324

2425
/**
2526
* A HTTP server which serves Web Socket requests at:
@@ -74,13 +75,13 @@ public static void main(String[] args) throws Exception {
7475
port = 8443;
7576
}
7677

77-
String keyStoreFilePath = System.getProperty("keystore.file.path");
78+
String keyStoreFilePath = SystemPropertyUtil.get("keystore.file.path");
7879
if (keyStoreFilePath == null || keyStoreFilePath.isEmpty()) {
7980
System.out.println("ERROR: System property keystore.file.path not set. Exiting now!");
8081
System.exit(1);
8182
}
8283

83-
String keyStoreFilePassword = System.getProperty("keystore.file.password");
84+
String keyStoreFilePassword = SystemPropertyUtil.get("keystore.file.password");
8485
if (keyStoreFilePassword == null || keyStoreFilePassword.isEmpty()) {
8586
System.out.println("ERROR: System property keystore.file.password not set. Exiting now!");
8687
System.exit(1);

example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerSslContext.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package io.netty.example.http.websocketx.sslserver;
1717

18+
import io.netty.util.internal.SystemPropertyUtil;
19+
1820
import javax.net.ssl.KeyManagerFactory;
1921
import javax.net.ssl.SSLContext;
2022
import java.io.FileInputStream;
@@ -56,14 +58,14 @@ private WebSocketSslServerSslContext() {
5658
SSLContext serverContext = null;
5759
try {
5860
// Key store (Server side certificate)
59-
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
61+
String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm");
6062
if (algorithm == null) {
6163
algorithm = "SunX509";
6264
}
6365

6466
try {
65-
String keyStoreFilePath = System.getProperty("keystore.file.path");
66-
String keyStoreFilePassword = System.getProperty("keystore.file.password");
67+
String keyStoreFilePath = SystemPropertyUtil.get("keystore.file.path");
68+
String keyStoreFilePassword = SystemPropertyUtil.get("keystore.file.password");
6769

6870
KeyStore ks = KeyStore.getInstance("JKS");
6971
FileInputStream fin = new FileInputStream(keyStoreFilePath);

example/src/main/java/io/netty/example/securechat/SecureChatSslContextFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.netty.example.securechat;
1717

1818
import io.netty.handler.ssl.SslHandler;
19+
import io.netty.util.internal.SystemPropertyUtil;
1920

2021
import java.security.KeyStore;
2122
import java.security.SecureRandom;
@@ -57,7 +58,7 @@ public final class SecureChatSslContextFactory {
5758
private static final SSLContext CLIENT_CONTEXT;
5859

5960
static {
60-
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
61+
String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm");
6162
if (algorithm == null) {
6263
algorithm = "SunX509";
6364
}

0 commit comments

Comments
 (0)