8296024: Usage of DirectBuffer::address should be guarded

Reviewed-by: mcimadamore, alanb, psandoz, bpb
This commit is contained in:
Per Minborg 2022-12-06 10:42:59 +00:00 committed by Alan Bateman
parent a9e6c62ba7
commit 84b927a05b
24 changed files with 635 additions and 430 deletions

View file

@ -25,6 +25,8 @@
package com.sun.crypto.provider;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Unsafe;
import sun.nio.ch.DirectBuffer;
import sun.security.jca.JCAUtil;
@ -92,6 +94,8 @@ abstract class GaloisCounterMode extends CipherSpi {
static final byte[] EMPTY_BUF = new byte[0];
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
private boolean initialized = false;
SymmetricCipher blockCipher;
@ -909,6 +913,8 @@ abstract class GaloisCounterMode extends CipherSpi {
*/
ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) {
if (src.isDirect() && dst.isDirect()) {
// The use of DirectBuffer::address below need not be guarded as
// no access is made to actual memory.
DirectBuffer dsrc = (DirectBuffer) src;
DirectBuffer ddst = (DirectBuffer) dst;
@ -946,7 +952,6 @@ abstract class GaloisCounterMode extends CipherSpi {
((DirectBuffer) dst).address() - dstaddr + dst.position()) {
return dst;
}
} else if (!src.isDirect() && !dst.isDirect()) {
// if src is read only, then we need a copy
if (!src.isReadOnly()) {
@ -1585,8 +1590,13 @@ abstract class GaloisCounterMode extends CipherSpi {
int ofs = dst.arrayOffset() + dst.position();
Arrays.fill(dst.array(), ofs , ofs + len, (byte)0);
} else {
Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(),
len + dst.position(), (byte)0);
NIO_ACCESS.acquireSession(dst);
try {
Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(),
len + dst.position(), (byte) 0);
} finally {
NIO_ACCESS.releaseSession(dst);
}
}
throw new AEADBadTagException("Tag mismatch");
}

View file

@ -37,6 +37,7 @@ import jdk.internal.vm.annotation.ForceInline;
import java.io.FileDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.ref.Reference;
import java.util.Objects;
import java.util.Spliterator;
@ -779,6 +780,7 @@ public abstract sealed class Buffer
// setup access to this package in SharedSecrets
SharedSecrets.setJavaNioAccess(
new JavaNioAccess() {
@Override
public BufferPool getDirectBufferPool() {
return Bits.BUFFER_POOL;
@ -824,16 +826,34 @@ public abstract sealed class Buffer
}
@Override
public Runnable acquireSession(Buffer buffer, boolean async) {
var session = buffer.session();
if (session == null) {
return null;
public void acquireSession(Buffer buffer) {
var scope = buffer.session();
if (scope != null) {
scope.acquire0();
}
if (async && session.ownerThread() != null) {
throw new IllegalStateException("Confined session not supported");
}
@Override
public void releaseSession(Buffer buffer) {
try {
var scope = buffer.session();
if (scope != null) {
scope.release0();
}
} finally {
Reference.reachabilityFence(buffer);
}
session.acquire0();
return session::release0;
}
@Override
public boolean isThreadConfined(Buffer buffer) {
var scope = buffer.session();
return scope != null && scope.ownerThread() != null;
}
@Override
public boolean hasSession(Buffer buffer) {
return buffer.session() != null;
}
@Override

View file

@ -25,11 +25,13 @@
package java.util.zip;
import java.lang.ref.Reference;
import java.nio.ByteBuffer;
import sun.nio.ch.DirectBuffer;
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import sun.nio.ch.DirectBuffer;
import static java.util.zip.ZipUtils.NIO_ACCESS;
/**
* A class that can be used to compute the Adler-32 checksum of a data
@ -96,10 +98,11 @@ public class Adler32 implements Checksum {
if (rem <= 0)
return;
if (buffer.isDirect()) {
NIO_ACCESS.acquireSession(buffer);
try {
adler = updateByteBuffer(adler, ((DirectBuffer)buffer).address(), pos, rem);
} finally {
Reference.reachabilityFence(buffer);
NIO_ACCESS.releaseSession(buffer);
}
} else if (buffer.hasArray()) {
adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem);

View file

@ -25,7 +25,6 @@
package java.util.zip;
import java.lang.ref.Reference;
import java.nio.ByteBuffer;
import java.util.Objects;
@ -33,6 +32,8 @@ import sun.nio.ch.DirectBuffer;
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import static java.util.zip.ZipUtils.NIO_ACCESS;
/**
* A class that can be used to compute the CRC-32 of a data stream.
*
@ -96,10 +97,11 @@ public class CRC32 implements Checksum {
if (rem <= 0)
return;
if (buffer.isDirect()) {
NIO_ACCESS.acquireSession(buffer);
try {
crc = updateByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, rem);
} finally {
Reference.reachabilityFence(buffer);
NIO_ACCESS.releaseSession(buffer);
}
} else if (buffer.hasArray()) {
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem);

View file

@ -24,7 +24,6 @@
*/
package java.util.zip;
import java.lang.ref.Reference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -33,6 +32,8 @@ import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import sun.nio.ch.DirectBuffer;
import static java.util.zip.ZipUtils.NIO_ACCESS;
/**
* A class that can be used to compute the CRC-32C of a data stream.
*
@ -171,11 +172,12 @@ public final class CRC32C implements Checksum {
}
if (buffer.isDirect()) {
NIO_ACCESS.acquireSession(buffer);
try {
crc = updateDirectByteBuffer(crc, ((DirectBuffer) buffer).address(),
crc = updateDirectByteBuffer(crc, ((DirectBuffer)buffer).address(),
pos, limit);
} finally {
Reference.reachabilityFence(buffer);
NIO_ACCESS.releaseSession(buffer);
}
} else if (buffer.hasArray()) {
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(),

View file

@ -26,7 +26,6 @@
package java.util.zip;
import java.lang.ref.Cleaner.Cleanable;
import java.lang.ref.Reference;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.util.Objects;
@ -35,6 +34,8 @@ import jdk.internal.ref.CleanerFactory;
import jdk.internal.util.Preconditions;
import sun.nio.ch.DirectBuffer;
import static java.util.zip.ZipUtils.NIO_ACCESS;
/**
* This class provides support for general purpose compression using the
* popular ZLIB compression library. The ZLIB compression library was
@ -337,11 +338,12 @@ public class Deflater {
int remaining = Math.max(dictionary.limit() - position, 0);
ensureOpen();
if (dictionary.isDirect()) {
long address = ((DirectBuffer) dictionary).address();
NIO_ACCESS.acquireSession(dictionary);
try {
long address = ((DirectBuffer) dictionary).address();
setDictionaryBuffer(zsRef.address(), address + position, remaining);
} finally {
Reference.reachabilityFence(dictionary);
NIO_ACCESS.releaseSession(dictionary);
}
} else {
byte[] array = ZipUtils.getBufferArray(dictionary);
@ -587,6 +589,7 @@ public class Deflater {
inputPos = input.position();
int inputRem = Math.max(input.limit() - inputPos, 0);
if (input.isDirect()) {
NIO_ACCESS.acquireSession(input);
try {
long inputAddress = ((DirectBuffer) input).address();
result = deflateBufferBytes(zsRef.address(),
@ -594,7 +597,7 @@ public class Deflater {
output, off, len,
flush, params);
} finally {
Reference.reachabilityFence(input);
NIO_ACCESS.releaseSession(input);
}
} else {
byte[] inputArray = ZipUtils.getBufferArray(input);
@ -709,14 +712,15 @@ public class Deflater {
if (input == null) {
inputPos = this.inputPos;
if (output.isDirect()) {
long outputAddress = ((DirectBuffer) output).address();
NIO_ACCESS.acquireSession(output);
try {
long outputAddress = ((DirectBuffer) output).address();
result = deflateBytesBuffer(zsRef.address(),
inputArray, inputPos, inputLim - inputPos,
outputAddress + outputPos, outputRem,
flush, params);
} finally {
Reference.reachabilityFence(output);
NIO_ACCESS.releaseSession(output);
}
} else {
byte[] outputArray = ZipUtils.getBufferArray(output);
@ -730,17 +734,19 @@ public class Deflater {
inputPos = input.position();
int inputRem = Math.max(input.limit() - inputPos, 0);
if (input.isDirect()) {
long inputAddress = ((DirectBuffer) input).address();
NIO_ACCESS.acquireSession(input);
try {
long inputAddress = ((DirectBuffer) input).address();
if (output.isDirect()) {
long outputAddress = outputPos + ((DirectBuffer) output).address();
NIO_ACCESS.acquireSession(output);
try {
long outputAddress = outputPos + ((DirectBuffer) output).address();
result = deflateBufferBuffer(zsRef.address(),
inputAddress + inputPos, inputRem,
outputAddress, outputRem,
flush, params);
} finally {
Reference.reachabilityFence(output);
NIO_ACCESS.releaseSession(output);
}
} else {
byte[] outputArray = ZipUtils.getBufferArray(output);
@ -751,20 +757,21 @@ public class Deflater {
flush, params);
}
} finally {
Reference.reachabilityFence(input);
NIO_ACCESS.releaseSession(input);
}
} else {
byte[] inputArray = ZipUtils.getBufferArray(input);
int inputOffset = ZipUtils.getBufferOffset(input);
if (output.isDirect()) {
long outputAddress = ((DirectBuffer) output).address();
NIO_ACCESS.acquireSession(output);
try {
long outputAddress = ((DirectBuffer) output).address();
result = deflateBytesBuffer(zsRef.address(),
inputArray, inputOffset + inputPos, inputRem,
outputAddress + outputPos, outputRem,
flush, params);
} finally {
Reference.reachabilityFence(output);
NIO_ACCESS.releaseSession(output);
}
} else {
byte[] outputArray = ZipUtils.getBufferArray(output);

View file

@ -26,7 +26,6 @@
package java.util.zip;
import java.lang.ref.Cleaner.Cleanable;
import java.lang.ref.Reference;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.util.Objects;
@ -35,6 +34,8 @@ import jdk.internal.ref.CleanerFactory;
import jdk.internal.util.Preconditions;
import sun.nio.ch.DirectBuffer;
import static java.util.zip.ZipUtils.NIO_ACCESS;
/**
* This class provides support for general purpose decompression using the
* popular ZLIB compression library. The ZLIB compression library was
@ -259,11 +260,12 @@ public class Inflater {
int remaining = Math.max(dictionary.limit() - position, 0);
ensureOpen();
if (dictionary.isDirect()) {
long address = ((DirectBuffer) dictionary).address();
NIO_ACCESS.acquireSession(dictionary);
try {
long address = ((DirectBuffer) dictionary).address();
setDictionaryBuffer(zsRef.address(), address + position, remaining);
} finally {
Reference.reachabilityFence(dictionary);
NIO_ACCESS.releaseSession(dictionary);
}
} else {
byte[] array = ZipUtils.getBufferArray(dictionary);
@ -383,13 +385,14 @@ public class Inflater {
try {
int inputRem = Math.max(input.limit() - inputPos, 0);
if (input.isDirect()) {
NIO_ACCESS.acquireSession(input);
try {
long inputAddress = ((DirectBuffer) input).address();
result = inflateBufferBytes(zsRef.address(),
inputAddress + inputPos, inputRem,
output, off, len);
} finally {
Reference.reachabilityFence(input);
NIO_ACCESS.releaseSession(input);
}
} else {
byte[] inputArray = ZipUtils.getBufferArray(input);
@ -517,13 +520,14 @@ public class Inflater {
inputPos = this.inputPos;
try {
if (output.isDirect()) {
long outputAddress = ((DirectBuffer) output).address();
NIO_ACCESS.acquireSession(output);
try {
long outputAddress = ((DirectBuffer) output).address();
result = inflateBytesBuffer(zsRef.address(),
inputArray, inputPos, inputLim - inputPos,
outputAddress + outputPos, outputRem);
} finally {
Reference.reachabilityFence(output);
NIO_ACCESS.releaseSession(output);
}
} else {
byte[] outputArray = ZipUtils.getBufferArray(output);
@ -541,16 +545,18 @@ public class Inflater {
int inputRem = Math.max(input.limit() - inputPos, 0);
try {
if (input.isDirect()) {
long inputAddress = ((DirectBuffer) input).address();
NIO_ACCESS.acquireSession(input);
try {
long inputAddress = ((DirectBuffer) input).address();
if (output.isDirect()) {
long outputAddress = ((DirectBuffer) output).address();
NIO_ACCESS.acquireSession(output);
try {
long outputAddress = ((DirectBuffer) output).address();
result = inflateBufferBuffer(zsRef.address(),
inputAddress + inputPos, inputRem,
outputAddress + outputPos, outputRem);
} finally {
Reference.reachabilityFence(output);
NIO_ACCESS.releaseSession(output);
}
} else {
byte[] outputArray = ZipUtils.getBufferArray(output);
@ -560,19 +566,20 @@ public class Inflater {
outputArray, outputOffset + outputPos, outputRem);
}
} finally {
Reference.reachabilityFence(input);
NIO_ACCESS.releaseSession(input);
}
} else {
byte[] inputArray = ZipUtils.getBufferArray(input);
int inputOffset = ZipUtils.getBufferOffset(input);
if (output.isDirect()) {
long outputAddress = ((DirectBuffer) output).address();
NIO_ACCESS.acquireSession(output);
try {
long outputAddress = ((DirectBuffer) output).address();
result = inflateBytesBuffer(zsRef.address(),
inputArray, inputOffset + inputPos, inputRem,
outputAddress + outputPos, outputRem);
} finally {
Reference.reachabilityFence(output);
NIO_ACCESS.releaseSession(output);
}
} else {
byte[] outputArray = ZipUtils.getBufferArray(output);

View file

@ -36,10 +36,14 @@ import java.util.concurrent.TimeUnit;
import static java.util.zip.ZipConstants.ENDHDR;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Unsafe;
class ZipUtils {
static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// used to adjust values between Windows and java epoch
private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;

View file

@ -86,12 +86,26 @@ public interface JavaNioAccess {
MemorySegment bufferSegment(Buffer buffer);
/**
* Used by I/O operations to make a buffer's session non-closeable
* (for the duration of the I/O operation) by acquiring the session.
* Null is returned if the buffer has no scope, or acquiring is not
* required to guarantee safety.
* Used by operations to make a buffer's session non-closeable
* (for the duration of the operation) by acquiring the session.
* {@snippet lang = java:
* acquireSession(buffer);
* try {
* performOperation(buffer);
* } finally {
* releaseSession(buffer);
* }
*}
*
* @see #releaseSession(Buffer)
*/
Runnable acquireSession(Buffer buffer, boolean async);
void acquireSession(Buffer buffer);
void releaseSession(Buffer buffer);
boolean isThreadConfined(Buffer buffer);
boolean hasSession(Buffer buffer);
/**
* Used by {@code jdk.internal.foreign.MappedMemorySegmentImpl} and byte buffer var handle views.

View file

@ -166,7 +166,9 @@ module java.base {
jdk.jartool,
jdk.jlink,
jdk.jfr,
jdk.net;
jdk.net,
jdk.sctp,
jdk.crypto.cryptoki;
exports jdk.internal.foreign to
jdk.incubator.vector;
exports jdk.internal.event to

View file

@ -71,6 +71,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.ref.CleanerFactory;
import sun.net.ResourceManager;
import sun.net.ext.ExtendedSocketOptions;
@ -87,6 +89,8 @@ class DatagramChannelImpl
// Used to make native read and write calls
private static final NativeDispatcher nd = new DatagramDispatcher();
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// true if interruptible (can be false to emulate legacy DatagramSocket)
private final boolean interruptible;
@ -780,13 +784,18 @@ class DatagramChannelImpl
boolean connected)
throws IOException
{
int n = receive0(fd,
((DirectBuffer)bb).address() + pos, rem,
sourceSockAddr.address(),
connected);
if (n > 0)
bb.position(pos + n);
return n;
NIO_ACCESS.acquireSession(bb);
try {
int n = receive0(fd,
((DirectBuffer)bb).address() + pos, rem,
sourceSockAddr.address(),
connected);
if (n > 0)
bb.position(pos + n);
return n;
} finally {
NIO_ACCESS.releaseSession(bb);
}
}
/**
@ -930,6 +939,7 @@ class DatagramChannelImpl
int rem = (pos <= lim ? lim - pos : 0);
int written;
NIO_ACCESS.acquireSession(bb);
try {
int addressLen = targetSocketAddress(target);
written = send0(fd, ((DirectBuffer)bb).address() + pos, rem,
@ -938,6 +948,8 @@ class DatagramChannelImpl
if (isConnected())
throw pue;
written = rem;
} finally {
NIO_ACCESS.releaseSession(bb);
}
if (written > 0)
bb.position(pos + written);

View file

@ -30,6 +30,13 @@ import jdk.internal.ref.Cleaner;
public interface DirectBuffer {
// Use of the returned address must be guarded if this DirectBuffer
// is backed by a memory session that is explicitly closeable.
//
// Failure to do this means the outcome is undefined including
// silent unrelated memory mutation and JVM crashes.
//
// See JavaNioAccess for methods to safely acquire/release resources.
public long address();
public Object attachment();

View file

@ -31,12 +31,13 @@ import java.nio.ByteBuffer;
import java.util.Objects;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.foreign.MemorySessionImpl;
/**
* File-descriptor based I/O utilities that are shared by NIO classes.
*/
public class IOUtil {
public final class IOUtil {
/**
* Max number of iovec structures that readv/writev supports
@ -128,7 +129,7 @@ public class IOUtil {
int written = 0;
if (rem == 0)
return 0;
var handle = acquireScope(bb, async);
acquireScope(bb, async);
try {
if (position != -1) {
written = nd.pwrite(fd, bufferAddress(bb) + pos, rem, position);
@ -136,7 +137,7 @@ public class IOUtil {
written = nd.write(fd, bufferAddress(bb) + pos, rem);
}
} finally {
releaseScope(handle);
releaseScope(bb);
}
if (written > 0)
bb.position(pos + written);
@ -181,9 +182,9 @@ public class IOUtil {
int i = offset;
while (i < count && iov_len < IOV_MAX && writevLen < WRITEV_MAX) {
ByteBuffer buf = bufs[i];
var h = acquireScope(buf, async);
if (h != null) {
handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers);
acquireScope(buf, async);
if (NIO_ACCESS.hasSession(buf)) {
handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers);
}
int pos = buf.position();
int lim = buf.limit();
@ -331,7 +332,7 @@ public class IOUtil {
if (rem == 0)
return 0;
int n = 0;
var handle = acquireScope(bb, async);
acquireScope(bb, async);
try {
if (position != -1) {
n = nd.pread(fd, bufferAddress(bb) + pos, rem, position);
@ -339,7 +340,7 @@ public class IOUtil {
n = nd.read(fd, bufferAddress(bb) + pos, rem);
}
} finally {
releaseScope(handle);
releaseScope(bb);
}
if (n > 0)
bb.position(pos + n);
@ -393,9 +394,9 @@ public class IOUtil {
ByteBuffer buf = bufs[i];
if (buf.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
var h = acquireScope(buf, async);
if (h != null) {
handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers);
acquireScope(buf, async);
if (NIO_ACCESS.hasSession(buf)) {
handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers);
}
int pos = buf.position();
int lim = buf.limit();
@ -474,15 +475,16 @@ public class IOUtil {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
static Runnable acquireScope(ByteBuffer bb, boolean async) {
return NIO_ACCESS.acquireSession(bb, async);
static void acquireScope(ByteBuffer bb, boolean async) {
if (async && NIO_ACCESS.isThreadConfined(bb)) {
throw new IllegalStateException("Confined session not supported");
}
NIO_ACCESS.acquireSession(bb);
}
private static void releaseScope(Runnable handle) {
if (handle == null)
return;
private static void releaseScope(ByteBuffer bb) {
try {
handle.run();
NIO_ACCESS.releaseSession(bb);
} catch (Exception e) {
throw new IllegalStateException(e);
}
@ -495,15 +497,14 @@ public class IOUtil {
static Runnable acquireScopes(ByteBuffer buf, ByteBuffer[] buffers) {
if (buffers == null) {
assert buf != null;
return IOUtil.Releaser.ofNullable(IOUtil.acquireScope(buf, true));
IOUtil.acquireScope(buf, true);
return IOUtil.Releaser.of(buf);
} else {
assert buf == null;
Runnable handleReleasers = null;
for (var b : buffers) {
var h = IOUtil.acquireScope(b, true);
if (h != null) {
handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(h), handleReleasers);
}
IOUtil.acquireScope(b, true);
handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(b), handleReleasers);
}
return handleReleasers;
}
@ -514,12 +515,11 @@ public class IOUtil {
releasers.run();
}
static record LinkedRunnable(Runnable node, Runnable next)
implements Runnable
{
record LinkedRunnable(Runnable node, Runnable next) implements Runnable {
LinkedRunnable {
Objects.requireNonNull(node);
}
@Override
public void run() {
try {
@ -529,20 +529,28 @@ public class IOUtil {
next.run();
}
}
static LinkedRunnable of(Runnable first, Runnable second) {
return new LinkedRunnable(first, second);
}
}
static record Releaser(Runnable handle) implements Runnable {
Releaser { Objects.requireNonNull(handle) ; }
@Override public void run() { releaseScope(handle); }
static Runnable of(Runnable handle) { return new Releaser(handle); }
static Runnable ofNullable(Runnable handle) {
if (handle == null)
return () -> { };
return new Releaser(handle);
record Releaser(ByteBuffer bb) implements Runnable {
Releaser {
Objects.requireNonNull(bb);
}
@Override
public void run() {
releaseScope(bb);
}
static Runnable of(ByteBuffer bb) {
return NIO_ACCESS.hasSession(bb)
? new Releaser(bb)
: () -> {};
}
}
static long bufferAddress(ByteBuffer buf) {

View file

@ -134,6 +134,7 @@ 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.jdk.internal.access";
permission java.lang.RuntimePermission
"accessClassInPackage.sun.security.*";
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";