8269034: AccessControlException for SunPKCS11 daemon threads

Reviewed-by: valeriep
This commit is contained in:
Sean Coffey 2021-06-29 22:52:45 +00:00
parent d042029509
commit 0d745ae8fd
5 changed files with 78 additions and 42 deletions

View File

@ -199,6 +199,7 @@ module java.base {
jdk.attach,
jdk.charsets,
jdk.compiler,
jdk.crypto.cryptoki,
jdk.incubator.vector,
jdk.jfr,
jdk.jshell,

View File

@ -128,6 +128,7 @@ grant codeBase "jrt:/jdk.crypto.ec" {
grant codeBase "jrt:/jdk.crypto.cryptoki" {
permission java.lang.RuntimePermission
"accessClassInPackage.com.sun.crypto.provider";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
permission java.lang.RuntimePermission
"accessClassInPackage.sun.security.*";
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";

View File

@ -42,6 +42,7 @@ import javax.security.auth.callback.PasswordCallback;
import com.sun.crypto.provider.ChaCha20Poly1305Parameters;
import jdk.internal.misc.InnocuousThread;
import sun.security.util.Debug;
import sun.security.util.ResourcesMgr;
import static sun.security.util.SecurityConstants.PROVIDER_VER;
@ -907,15 +908,11 @@ public final class SunPKCS11 extends AuthProvider {
// background thread that periodically checks for token insertion
// if no token is present. We need to do that in a separate thread because
// the insertion check may block for quite a long time on some tokens.
private static class TokenPoller extends Thread {
private static class TokenPoller implements Runnable {
private final SunPKCS11 provider;
private volatile boolean enabled;
private TokenPoller(SunPKCS11 provider) {
super((ThreadGroup)null, "Poller-" + provider.getName());
setContextClassLoader(null);
setDaemon(true);
setPriority(Thread.MIN_PRIORITY);
this.provider = provider;
enabled = true;
}
@ -944,12 +941,20 @@ public final class SunPKCS11 extends AuthProvider {
}
// create the poller thread, if not already active
@SuppressWarnings("removal")
private void createPoller() {
if (poller != null) {
return;
}
poller = new TokenPoller(this);
poller.start();
Thread t = InnocuousThread.newSystemThread(
"Poller-" + getName(),
poller,
Thread.MIN_PRIORITY);
assert t.getContextClassLoader() == null;
t.setDaemon(true);
t.start();
}
// destroy the poller thread, if active
@ -972,18 +977,11 @@ public final class SunPKCS11 extends AuthProvider {
return (token != null) && token.isValid();
}
private class NativeResourceCleaner extends Thread {
private class NativeResourceCleaner implements Runnable {
private long sleepMillis = config.getResourceCleanerShortInterval();
private int count = 0;
boolean keyRefFound, sessRefFound;
private NativeResourceCleaner() {
super((ThreadGroup)null, "Cleanup-SunPKCS11");
setContextClassLoader(null);
setDaemon(true);
setPriority(Thread.MIN_PRIORITY);
}
/*
* The cleaner.shortInterval and cleaner.longInterval properties
* may be defined in the pkcs11 config file and are specified in milliseconds
@ -1001,7 +999,7 @@ public final class SunPKCS11 extends AuthProvider {
public void run() {
while (true) {
try {
sleep(sleepMillis);
Thread.sleep(sleepMillis);
} catch (InterruptedException ie) {
break;
}
@ -1022,6 +1020,19 @@ public final class SunPKCS11 extends AuthProvider {
}
}
// create the cleaner thread, if not already active
@SuppressWarnings("removal")
private void createCleaner() {
cleaner = new NativeResourceCleaner();
Thread t = InnocuousThread.newSystemThread(
"Cleanup-SunPKCS11",
cleaner,
Thread.MIN_PRIORITY);
assert t.getContextClassLoader() == null;
t.setDaemon(true);
t.start();
}
// destroy the token. Called if we detect that it has been removed
@SuppressWarnings("removal")
synchronized void uninitToken(Token token) {
@ -1190,8 +1201,7 @@ public final class SunPKCS11 extends AuthProvider {
this.token = token;
if (cleaner == null) {
cleaner = new NativeResourceCleaner();
cleaner.start();
createCleaner();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@ -31,10 +31,9 @@ import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.security.*;
import java.util.Iterator;
import java.util.PropertyPermission;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
@ -44,19 +43,28 @@ public class MultipleLogins {
private static final String KS_TYPE = "PKCS11";
private static final int NUM_PROVIDERS = 20;
private static final SunPKCS11[] providers = new SunPKCS11[NUM_PROVIDERS];
static final Policy DEFAULT_POLICY = Policy.getPolicy();
public static void main(String[] args) throws Exception {
String nssConfig = PKCS11Test.getNssConfig();
if (nssConfig == null) {
// No test framework support yet. Ignore
System.out.println("No NSS config found. Skipping.");
return;
}
for (int i =0; i < NUM_PROVIDERS; i++) {
String nssConfig = PKCS11Test.getNssConfig();
if (nssConfig == null) {
// No test framework support yet. Ignore
System.out.println("No NSS config found. Skipping.");
return;
}
providers[i] =
(SunPKCS11)PKCS11Test.newPKCS11Provider()
.configure(nssConfig);
// loop to set up test without security manger
providers[i] = (SunPKCS11)PKCS11Test.newPKCS11Provider();
}
if (args.length > 0) {
Policy.setPolicy(new SimplePolicy());
System.setSecurityManager(new SecurityManager());
}
for (int i =0; i < NUM_PROVIDERS; i++) {
providers[i] = (SunPKCS11)providers[i].configure(nssConfig);
Security.addProvider(providers[i]);
test(providers[i]);
}
@ -92,7 +100,6 @@ public class MultipleLogins {
private static void test(SunPKCS11 p) throws Exception {
KeyStore ks = KeyStore.getInstance(KS_TYPE, p);
p.setCallbackHandler(new PasswordCallbackHandler());
try {
ks.load(null, (char[]) null);
@ -117,6 +124,23 @@ public class MultipleLogins {
}
}
static final class SimplePolicy extends Policy {
final Permissions perms = new Permissions();
SimplePolicy() {
perms.add(new PropertyPermission("*", "read, write"));
perms.add(new SecurityPermission("authProvider.*"));
perms.add(new SecurityPermission("insertProvider.*"));
perms.add(new SecurityPermission("removeProvider.*"));
}
@Override
public boolean implies(ProtectionDomain domain, Permission permission) {
return perms.implies(permission) ||
DEFAULT_POLICY.implies(domain, permission);
}
}
public static class PasswordCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {

View File

@ -22,7 +22,7 @@
#
# @test
# @bug 7777777
# @bug 8240256 8269034
# @summary
# @library /test/lib/
# @build jdk.test.lib.util.ForceGC
@ -114,9 +114,7 @@ ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
${TESTSRC}${FS}MultipleLogins.java \
${TESTSRC}${FS}..${FS}PKCS11Test.java
# run test
${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
-classpath ${TESTCLASSPATH} \
TEST_ARGS="${TESTVMOPTS} -classpath ${TESTCLASSPATH} \
--add-modules jdk.crypto.cryptoki \
--add-exports jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED \
-DCUSTOM_DB_DIR=${TESTCLASSES} \
@ -125,11 +123,13 @@ ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \
-DNO_DEIMOS=true \
-Dtest.src=${TESTSRC} \
-Dtest.classes=${TESTCLASSES} \
-Djava.security.debug=${DEBUG} \
MultipleLogins
-Djava.security.debug=${DEBUG}"
# save error status
status=$?
# run test without security manager
${TESTJAVA}${FS}bin${FS}java ${TEST_ARGS} MultipleLogins || exit 10
# return
exit $status
# run test with security manager
${TESTJAVA}${FS}bin${FS}java ${TEST_ARGS} MultipleLogins useSimplePolicy || exit 11
echo Done
exit 0