diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index e639a016ff117..d55aff3549934 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -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 @@ int doLastBlock(GCMOperation op, ByteBuffer buffer, ByteBuffer src, */ 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 @@ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { ((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 @@ public int doFinal(ByteBuffer src, ByteBuffer dst) 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"); } diff --git a/src/java.base/share/classes/java/nio/Buffer.java b/src/java.base/share/classes/java/nio/Buffer.java index 229a4fb4f23b7..06d28a066bfdd 100644 --- a/src/java.base/share/classes/java/nio/Buffer.java +++ b/src/java.base/share/classes/java/nio/Buffer.java @@ -37,6 +37,7 @@ 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 @@ final void checkSession() { // setup access to this package in SharedSecrets SharedSecrets.setJavaNioAccess( new JavaNioAccess() { + @Override public BufferPool getDirectBufferPool() { return Bits.BUFFER_POOL; @@ -824,16 +826,34 @@ public MemorySegment bufferSegment(Buffer 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 diff --git a/src/java.base/share/classes/java/util/zip/Adler32.java b/src/java.base/share/classes/java/util/zip/Adler32.java index 3c3adec344d34..b8e0bc190c128 100644 --- a/src/java.base/share/classes/java/util/zip/Adler32.java +++ b/src/java.base/share/classes/java/util/zip/Adler32.java @@ -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 void update(ByteBuffer buffer) { 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); diff --git a/src/java.base/share/classes/java/util/zip/CRC32.java b/src/java.base/share/classes/java/util/zip/CRC32.java index 9d41392d172a2..84e6f26e45e83 100644 --- a/src/java.base/share/classes/java/util/zip/CRC32.java +++ b/src/java.base/share/classes/java/util/zip/CRC32.java @@ -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 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 void update(ByteBuffer buffer) { 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); diff --git a/src/java.base/share/classes/java/util/zip/CRC32C.java b/src/java.base/share/classes/java/util/zip/CRC32C.java index a8b4d1b75659d..a813e91000994 100644 --- a/src/java.base/share/classes/java/util/zip/CRC32C.java +++ b/src/java.base/share/classes/java/util/zip/CRC32C.java @@ -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.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 void update(ByteBuffer buffer) { } 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(), diff --git a/src/java.base/share/classes/java/util/zip/Deflater.java b/src/java.base/share/classes/java/util/zip/Deflater.java index 155264e4afe4b..3e550d141788c 100644 --- a/src/java.base/share/classes/java/util/zip/Deflater.java +++ b/src/java.base/share/classes/java/util/zip/Deflater.java @@ -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.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 void setDictionary(ByteBuffer dictionary) { 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 int deflate(byte[] output, int off, int len, int flush) { 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 int deflate(byte[] output, int off, int len, int flush) { output, off, len, flush, params); } finally { - Reference.reachabilityFence(input); + NIO_ACCESS.releaseSession(input); } } else { byte[] inputArray = ZipUtils.getBufferArray(input); @@ -709,14 +712,15 @@ public int deflate(ByteBuffer output, int flush) { 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 int deflate(ByteBuffer output, int flush) { 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 int deflate(ByteBuffer output, int flush) { 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); diff --git a/src/java.base/share/classes/java/util/zip/Inflater.java b/src/java.base/share/classes/java/util/zip/Inflater.java index 8a7f742f41f0c..a3cbdd1d1bf56 100644 --- a/src/java.base/share/classes/java/util/zip/Inflater.java +++ b/src/java.base/share/classes/java/util/zip/Inflater.java @@ -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.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 void setDictionary(ByteBuffer dictionary) { 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 int inflate(byte[] output, int off, int len) 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 int inflate(ByteBuffer output) throws DataFormatException { 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 int inflate(ByteBuffer output) throws DataFormatException { 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 int inflate(ByteBuffer output) throws DataFormatException { 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); diff --git a/src/java.base/share/classes/java/util/zip/ZipUtils.java b/src/java.base/share/classes/java/util/zip/ZipUtils.java index cca1454f5bec0..0cbc2e28795d8 100644 --- a/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -36,10 +36,14 @@ 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; diff --git a/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java index 9e54ef59884e5..b34a0d42085aa 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java @@ -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. - */ - Runnable acquireSession(Buffer buffer, boolean async); + * 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) + */ + 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. diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index d75b1d9a1ffc9..86d8866049c3d 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -166,7 +166,9 @@ 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 diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index e1651e3101438..d8f7cd0cb7270 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -71,6 +71,8 @@ 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 @@ private int receiveIntoNativeBuffer(ByteBuffer bb, int rem, int pos, 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 @@ private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, 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 @@ private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, if (isConnected()) throw pue; written = rem; + } finally { + NIO_ACCESS.releaseSession(bb); } if (written > 0) bb.position(pos + written); diff --git a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java index cba31015f0ca8..8fcea1eb57d12 100644 --- a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java +++ b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java @@ -30,6 +30,13 @@ 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(); diff --git a/src/java.base/share/classes/sun/nio/ch/IOUtil.java b/src/java.base/share/classes/sun/nio/ch/IOUtil.java index 6ed206e9a230a..55522fd717dea 100644 --- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java +++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java @@ -31,12 +31,13 @@ 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 @@ private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, 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 @@ private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, written = nd.write(fd, bufferAddress(bb) + pos, rem); } } finally { - releaseScope(handle); + releaseScope(bb); } if (written > 0) bb.position(pos + written); @@ -181,9 +182,9 @@ static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 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 @@ private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, 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 @@ private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, n = nd.read(fd, bufferAddress(bb) + pos, rem); } } finally { - releaseScope(handle); + releaseScope(bb); } if (n > 0) bb.position(pos + n); @@ -393,9 +394,9 @@ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 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 @@ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 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 @@ static Runnable acquireScopes(ByteBuffer[] buffers) { 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 @@ static void releaseScopes(Runnable releasers) { 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 void run() { 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) { diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy index 39a57aa937299..2a01c06250a1c 100644 --- a/src/java.base/share/lib/security/default.policy +++ b/src/java.base/share/lib/security/default.policy @@ -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"; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java index fe28dd6ce2665..41528a55e3767 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java @@ -25,11 +25,13 @@ package sun.nio.fs; -import java.lang.ref.Reference; import java.nio.file.*; import java.nio.ByteBuffer; import java.io.IOException; import java.util.*; + +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixConstants.*; @@ -43,6 +45,8 @@ abstract class UnixUserDefinedFileAttributeView { private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // namespace for extended user attributes private static final String USER_NAMESPACE = "user."; @@ -174,14 +178,15 @@ public int read(String name, ByteBuffer dst) throws IOException { assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - if (dst instanceof sun.nio.ch.DirectBuffer buf) { + if (dst instanceof sun.nio.ch.DirectBuffer ddst) { + NIO_ACCESS.acquireSession(dst); try { - long address = buf.address() + pos; + long address = ddst.address() + pos; int n = read(name, address, rem); dst.position(pos + n); return n; } finally { - Reference.reachabilityFence(buf); + NIO_ACCESS.releaseSession(dst); } } else { try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) { @@ -237,13 +242,14 @@ public int write(String name, ByteBuffer src) throws IOException { int rem = (pos <= lim ? lim - pos : 0); if (src instanceof sun.nio.ch.DirectBuffer buf) { + NIO_ACCESS.acquireSession(src); try { long address = buf.address() + pos; write(name, address, rem); src.position(pos + rem); return rem; } finally { - Reference.reachabilityFence(buf); + NIO_ACCESS.releaseSession(src); } } else { try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java index 2a833dbd77ab3..7a91d17e74c05 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -35,6 +35,8 @@ import javax.crypto.*; import javax.crypto.spec.*; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; @@ -55,6 +57,8 @@ */ final class P11AEADCipher extends CipherSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // supported AEAD algorithms/transformations private enum Transformation { AES_GCM("AES", "GCM", "NOPADDING", 16, 16), @@ -705,84 +709,94 @@ private int implDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) } boolean doCancel = true; + NIO_ACCESS.acquireSession(inBuffer); try { - ensureInitialized(); - - long inAddr = 0; - byte[] in = null; - int inOfs = 0; - if (dataBuffer.size() > 0) { - if (inLen > 0) { - byte[] temp = new byte[inLen]; - inBuffer.get(temp); - dataBuffer.write(temp, 0, temp.length); - } - in = dataBuffer.toByteArray(); - inOfs = 0; - inLen = in.length; - } else { - if (inBuffer instanceof DirectBuffer) { - inAddr = ((DirectBuffer) inBuffer).address(); - inOfs = inBuffer.position(); - } else { - if (inBuffer.hasArray()) { - in = inBuffer.array(); - inOfs = inBuffer.position() + inBuffer.arrayOffset(); + NIO_ACCESS.acquireSession(outBuffer); + try { + try { + ensureInitialized(); + + long inAddr = 0; + byte[] in = null; + int inOfs = 0; + if (dataBuffer.size() > 0) { + if (inLen > 0) { + byte[] temp = new byte[inLen]; + inBuffer.get(temp); + dataBuffer.write(temp, 0, temp.length); + } + in = dataBuffer.toByteArray(); + inOfs = 0; + inLen = in.length; } else { - in = new byte[inLen]; - inBuffer.get(in); + if (inBuffer instanceof DirectBuffer dInBuffer) { + inAddr = dInBuffer.address(); + inOfs = inBuffer.position(); + } else { + if (inBuffer.hasArray()) { + in = inBuffer.array(); + inOfs = inBuffer.position() + inBuffer.arrayOffset(); + } else { + in = new byte[inLen]; + inBuffer.get(in); + } + } + } + long outAddr = 0; + byte[] outArray = null; + int outOfs = 0; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); + } else { + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = outBuffer.position() + outBuffer.arrayOffset(); + } else { + outArray = new byte[outLen]; + } } - } - } - long outAddr = 0; - byte[] outArray = null; - int outOfs = 0; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = outBuffer.position() + outBuffer.arrayOffset(); - } else { - outArray = new byte[outLen]; - } - } - int k = 0; - if (encrypt) { - k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; - } else { - // Special handling to match SunJCE provider behavior - if (inLen == 0) { - return 0; + int k = 0; + if (encrypt) { + k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } else { + // Special handling to match SunJCE provider behavior + if (inLen == 0) { + return 0; + } + k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } + inBuffer.position(inBuffer.limit()); + outBuffer.position(outBuffer.position() + k); + return k; + } catch (PKCS11Exception e) { + // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only + // keep the operation active on CKR_BUFFER_TOO_SMALL errors or + // successful calls to determine the output length. However, + // these cases are not expected here because the output length + // is checked in the OpenJDK side before making the PKCS#11 call. + // Thus, doCancel can safely be 'false'. + doCancel = false; + handleException(e); + throw new ProviderException("doFinal() failed", e); + } finally { + if (encrypt) { + lastEncKey = this.p11Key; + lastEncIv = this.iv; + requireReinit = true; + } + reset(doCancel); } - k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; + } finally { + NIO_ACCESS.releaseSession(outBuffer); } - inBuffer.position(inBuffer.limit()); - outBuffer.position(outBuffer.position() + k); - return k; - } catch (PKCS11Exception e) { - // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only - // keep the operation active on CKR_BUFFER_TOO_SMALL errors or - // successful calls to determine the output length. However, - // these cases are not expected here because the output length - // is checked in the OpenJDK side before making the PKCS#11 call. - // Thus, doCancel can safely be 'false'. - doCancel = false; - handleException(e); - throw new ProviderException("doFinal() failed", e); } finally { - if (encrypt) { - lastEncKey = this.p11Key; - lastEncIv = this.iv; - requireReinit = true; - } - reset(doCancel); + NIO_ACCESS.releaseSession(inBuffer); } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java index 2574ae685ac78..873c69d5b008b 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java @@ -34,6 +34,8 @@ import javax.crypto.*; import javax.crypto.spec.*; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; @@ -56,6 +58,8 @@ */ final class P11Cipher extends CipherSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // mode constant for ECB mode private static final int MODE_ECB = 3; // mode constant for CBC mode @@ -678,115 +682,123 @@ private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer) throw new ShortBufferException(); } int origPos = inBuffer.position(); + NIO_ACCESS.acquireSession(inBuffer); try { - ensureInitialized(); - - long inAddr = 0; - int inOfs = 0; - byte[] inArray = null; - - if (inBuffer instanceof DirectBuffer) { - inAddr = ((DirectBuffer) inBuffer).address(); - inOfs = origPos; - } else if (inBuffer.hasArray()) { - inArray = inBuffer.array(); - inOfs = (origPos + inBuffer.arrayOffset()); - } + NIO_ACCESS.acquireSession(outBuffer); + try { + ensureInitialized(); + + long inAddr = 0; + int inOfs = 0; + byte[] inArray = null; + + if (inBuffer instanceof DirectBuffer dInBuffer) { + inAddr = dInBuffer.address(); + inOfs = origPos; + } else if (inBuffer.hasArray()) { + inArray = inBuffer.array(); + inOfs = (origPos + inBuffer.arrayOffset()); + } - long outAddr = 0; - int outOfs = 0; - byte[] outArray = null; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = (outBuffer.position() + outBuffer.arrayOffset()); + long outAddr = 0; + int outOfs = 0; + byte[] outArray = null; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); } else { - outArray = new byte[outLen]; + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = (outBuffer.position() + outBuffer.arrayOffset()); + } else { + outArray = new byte[outLen]; + } } - } - int k = 0; - int newPadBufferLen = 0; - if (paddingObj != null && (!encrypt || reqBlockUpdates)) { - if (padBufferLen != 0) { - if (padBufferLen != padBuffer.length) { - int bufCapacity = padBuffer.length - padBufferLen; - if (inLen > bufCapacity) { - bufferInputBytes(inBuffer, bufCapacity); - inOfs += bufCapacity; - inLen -= bufCapacity; + int k = 0; + int newPadBufferLen = 0; + if (paddingObj != null && (!encrypt || reqBlockUpdates)) { + if (padBufferLen != 0) { + if (padBufferLen != padBuffer.length) { + int bufCapacity = padBuffer.length - padBufferLen; + if (inLen > bufCapacity) { + bufferInputBytes(inBuffer, bufCapacity); + inOfs += bufCapacity; + inLen -= bufCapacity; + } else { + bufferInputBytes(inBuffer, inLen); + return 0; + } + } + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), 0, + padBuffer, 0, padBufferLen, outAddr, outArray, + outOfs, outLen); } else { - bufferInputBytes(inBuffer, inLen); - return 0; + k = token.p11.C_DecryptUpdate(session.id(), 0, + padBuffer, 0, padBufferLen, outAddr, outArray, + outOfs, outLen); } + padBufferLen = 0; + } + newPadBufferLen = inLen & (blockSize - 1); + if (!encrypt && newPadBufferLen == 0) { + // While decrypting with implUpdate, the last encrypted block + // is always held in a buffer. If it's the final one (unknown + // at this point), it may contain padding bytes and need further + // processing. In implDoFinal (where we know it's the final one) + // the buffer is decrypted, unpadded and returned. + newPadBufferLen = padBuffer.length; + } + inLen -= newPadBufferLen; + } + if (inLen > 0) { + if (inAddr == 0 && inArray == null) { + inArray = new byte[inLen]; + inBuffer.get(inArray); + } else { + inBuffer.position(inBuffer.position() + inLen); } if (encrypt) { - k = token.p11.C_EncryptUpdate(session.id(), 0, - padBuffer, 0, padBufferLen, outAddr, outArray, - outOfs, outLen); + k += token.p11.C_EncryptUpdate(session.id(), inAddr, + inArray, inOfs, inLen, outAddr, outArray, + (outOfs + k), (outLen - k)); } else { - k = token.p11.C_DecryptUpdate(session.id(), 0, - padBuffer, 0, padBufferLen, outAddr, outArray, - outOfs, outLen); + k += token.p11.C_DecryptUpdate(session.id(), inAddr, + inArray, inOfs, inLen, outAddr, outArray, + (outOfs + k), (outLen - k)); } - padBufferLen = 0; } - newPadBufferLen = inLen & (blockSize - 1); - if (!encrypt && newPadBufferLen == 0) { - // While decrypting with implUpdate, the last encrypted block - // is always held in a buffer. If it's the final one (unknown - // at this point), it may contain padding bytes and need further - // processing. In implDoFinal (where we know it's the final one) - // the buffer is decrypted, unpadded and returned. - newPadBufferLen = padBuffer.length; + // update 'padBuffer' if using our own padding impl. + if (paddingObj != null && newPadBufferLen > 0) { + bufferInputBytes(inBuffer, newPadBufferLen); } - inLen -= newPadBufferLen; - } - if (inLen > 0) { - if (inAddr == 0 && inArray == null) { - inArray = new byte[inLen]; - inBuffer.get(inArray); + bytesBuffered += (inLen - k); + if (!(outBuffer instanceof DirectBuffer) && + !outBuffer.hasArray()) { + outBuffer.put(outArray, outOfs, k); } else { - inBuffer.position(inBuffer.position() + inLen); + outBuffer.position(outBuffer.position() + k); } - if (encrypt) { - k += token.p11.C_EncryptUpdate(session.id(), inAddr, - inArray, inOfs, inLen, outAddr, outArray, - (outOfs + k), (outLen - k)); - } else { - k += token.p11.C_DecryptUpdate(session.id(), inAddr, - inArray, inOfs, inLen, outAddr, outArray, - (outOfs + k), (outLen - k)); + return k; + } catch (PKCS11Exception e) { + // Reset input buffer to its original position for + inBuffer.position(origPos); + if (e.match(CKR_BUFFER_TOO_SMALL)) { + throw (ShortBufferException) + (new ShortBufferException().initCause(e)); } + // Some implementations such as the NSS Software Token do not + // cancel the operation upon a C_EncryptUpdate/C_DecryptUpdate + // failure (as required by the PKCS#11 standard). See JDK-8258833 + // for further information. + reset(true); + throw new ProviderException("update() failed", e); + } finally { + NIO_ACCESS.releaseSession(outBuffer); } - // update 'padBuffer' if using our own padding impl. - if (paddingObj != null && newPadBufferLen > 0) { - bufferInputBytes(inBuffer, newPadBufferLen); - } - bytesBuffered += (inLen - k); - if (!(outBuffer instanceof DirectBuffer) && - !outBuffer.hasArray()) { - outBuffer.put(outArray, outOfs, k); - } else { - outBuffer.position(outBuffer.position() + k); - } - return k; - } catch (PKCS11Exception e) { - // Reset input buffer to its original position for - inBuffer.position(origPos); - if (e.match(CKR_BUFFER_TOO_SMALL)) { - throw (ShortBufferException) - (new ShortBufferException().initCause(e)); - } - // Some implementations such as the NSS Software Token do not - // cancel the operation upon a C_EncryptUpdate/C_DecryptUpdate - // failure (as required by the PKCS#11 standard). See JDK-8258833 - // for further information. - reset(true); - throw new ProviderException("update() failed", e); + } finally { + NIO_ACCESS.releaseSession(inBuffer); } } @@ -877,99 +889,104 @@ private int implDoFinal(ByteBuffer outBuffer) } boolean doCancel = true; + NIO_ACCESS.acquireSession(outBuffer); try { - ensureInitialized(); - - long outAddr = 0; - byte[] outArray = null; - int outOfs = 0; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = outBuffer.position() + outBuffer.arrayOffset(); + try { + ensureInitialized(); + + long outAddr = 0; + byte[] outArray = null; + int outOfs = 0; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); } else { - outArray = new byte[outLen]; + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = outBuffer.position() + outBuffer.arrayOffset(); + } else { + outArray = new byte[outLen]; + } } - } - int k = 0; + int k = 0; - if (encrypt) { - if (paddingObj != null) { - int startOff = 0; - if (reqBlockUpdates) { - // call C_EncryptUpdate first if the padBuffer is full - // to make room for padding bytes - if (padBufferLen == padBuffer.length) { - k = token.p11.C_EncryptUpdate(session.id(), - 0, padBuffer, 0, padBufferLen, - outAddr, outArray, outOfs, outLen); - } else { - startOff = padBufferLen; + if (encrypt) { + if (paddingObj != null) { + int startOff = 0; + if (reqBlockUpdates) { + // call C_EncryptUpdate first if the padBuffer is full + // to make room for padding bytes + if (padBufferLen == padBuffer.length) { + k = token.p11.C_EncryptUpdate(session.id(), + 0, padBuffer, 0, padBufferLen, + outAddr, outArray, outOfs, outLen); + } else { + startOff = padBufferLen; + } } - } - int actualPadLen = paddingObj.setPaddingBytes(padBuffer, - startOff, requiredOutLen - bytesBuffered); - k += token.p11.C_EncryptUpdate(session.id(), - 0, padBuffer, 0, startOff + actualPadLen, - outAddr, outArray, outOfs + k, outLen - k); - } - // Some implementations such as the NSS Software Token do not - // cancel the operation upon a C_EncryptUpdate failure (as - // required by the PKCS#11 standard). Cancel is not needed - // only after this point. See JDK-8258833 for further - // information. - doCancel = false; - k += token.p11.C_EncryptFinal(session.id(), - outAddr, outArray, (outOfs + k), (outLen - k)); - } else { - // Special handling to match SunJCE provider behavior - if (bytesBuffered == 0 && padBufferLen == 0) { - return 0; - } - - if (paddingObj != null) { - if (padBufferLen != 0) { - k = token.p11.C_DecryptUpdate(session.id(), - 0, padBuffer, 0, padBufferLen, - 0, padBuffer, 0, padBuffer.length); - padBufferLen = 0; + int actualPadLen = paddingObj.setPaddingBytes(padBuffer, + startOff, requiredOutLen - bytesBuffered); + k += token.p11.C_EncryptUpdate(session.id(), + 0, padBuffer, 0, startOff + actualPadLen, + outAddr, outArray, outOfs + k, outLen - k); } // Some implementations such as the NSS Software Token do not - // cancel the operation upon a C_DecryptUpdate failure (as + // cancel the operation upon a C_EncryptUpdate failure (as // required by the PKCS#11 standard). Cancel is not needed // only after this point. See JDK-8258833 for further // information. doCancel = false; - k += token.p11.C_DecryptFinal(session.id(), - 0, padBuffer, k, padBuffer.length - k); + k += token.p11.C_EncryptFinal(session.id(), + outAddr, outArray, (outOfs + k), (outLen - k)); + } else { + // Special handling to match SunJCE provider behavior + if (bytesBuffered == 0 && padBufferLen == 0) { + return 0; + } - int actualPadLen = paddingObj.unpad(padBuffer, k); - k -= actualPadLen; - outArray = padBuffer; - outOfs = 0; + if (paddingObj != null) { + if (padBufferLen != 0) { + k = token.p11.C_DecryptUpdate(session.id(), + 0, padBuffer, 0, padBufferLen, + 0, padBuffer, 0, padBuffer.length); + padBufferLen = 0; + } + // Some implementations such as the NSS Software Token do not + // cancel the operation upon a C_DecryptUpdate failure (as + // required by the PKCS#11 standard). Cancel is not needed + // only after this point. See JDK-8258833 for further + // information. + doCancel = false; + k += token.p11.C_DecryptFinal(session.id(), + 0, padBuffer, k, padBuffer.length - k); + + int actualPadLen = paddingObj.unpad(padBuffer, k); + k -= actualPadLen; + outArray = padBuffer; + outOfs = 0; + } else { + doCancel = false; + k = token.p11.C_DecryptFinal(session.id(), + outAddr, outArray, outOfs, outLen); + } + } + if ((!encrypt && paddingObj != null) || + (!(outBuffer instanceof DirectBuffer) && + !outBuffer.hasArray())) { + outBuffer.put(outArray, outOfs, k); } else { - doCancel = false; - k = token.p11.C_DecryptFinal(session.id(), - outAddr, outArray, outOfs, outLen); + outBuffer.position(outBuffer.position() + k); } + return k; + } catch (PKCS11Exception e) { + handleException(e); + throw new ProviderException("doFinal() failed", e); + } finally { + reset(doCancel); } - if ((!encrypt && paddingObj != null) || - (!(outBuffer instanceof DirectBuffer) && - !outBuffer.hasArray())) { - outBuffer.put(outArray, outOfs, k); - } else { - outBuffer.position(outBuffer.position() + k); - } - return k; - } catch (PKCS11Exception e) { - handleException(e); - throw new ProviderException("doFinal() failed", e); } finally { - reset(doCancel); + NIO_ACCESS.releaseSession(outBuffer); } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java index 1c667ae58e9a6..5a0aec89aa195 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java @@ -25,13 +25,14 @@ package sun.security.pkcs11; -import java.util.*; import java.nio.ByteBuffer; import java.security.*; import javax.crypto.SecretKey; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.util.MessageDigestSpi2; @@ -55,6 +56,8 @@ final class P11Digest extends MessageDigestSpi implements Cloneable, MessageDigestSpi2 { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + /* fields initialized, no session acquired */ private static final int S_BLANK = 1; @@ -268,13 +271,12 @@ protected void engineUpdate(ByteBuffer byteBuffer) { return; } - if (!(byteBuffer instanceof DirectBuffer)) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { super.engineUpdate(byteBuffer); return; } fetchSession(); - long addr = ((DirectBuffer)byteBuffer).address(); int ofs = byteBuffer.position(); try { if (state == S_BUFFERED) { @@ -285,7 +287,12 @@ protected void engineUpdate(ByteBuffer byteBuffer) { token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs); bufOfs = 0; } - token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len); + NIO_ACCESS.acquireSession(byteBuffer); + try { + token.p11.C_DigestUpdate(session.id(), dByteBuffer.address() + ofs, null, 0, len); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); + } byteBuffer.position(ofs + len); } catch (PKCS11Exception e) { engineReset(); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java index 12dfcf6004e5c..cdd01d6f5fcd1 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java @@ -37,13 +37,14 @@ import java.util.HexFormat; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; import static sun.security.pkcs11.TemplateManager.*; -import static sun.security.pkcs11.P11Cipher.*; /** * P11 KeyWrap Cipher implementation class for native impl which only support @@ -58,6 +59,8 @@ */ final class P11KeyWrapCipher extends CipherSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private static final int BLK_SIZE = 8; // supported mode and padding with AES cipher @@ -552,78 +555,88 @@ private int implDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) boolean doCancel = true; int k = 0; + NIO_ACCESS.acquireSession(inBuffer); try { - ensureInitialized(); - - long inAddr = 0; - byte[] in = null; - int inOfs = 0; - - if (dataBuffer.size() > 0) { - if (inBuffer != null && inLen > 0) { - byte[] temp = new byte[inLen]; - inBuffer.get(temp); - dataBuffer.write(temp, 0, temp.length); - } - - in = dataBuffer.toByteArray(); - inOfs = 0; - inLen = in.length; - } else { - if (inBuffer instanceof DirectBuffer) { - inAddr = ((DirectBuffer) inBuffer).address(); - inOfs = inBuffer.position(); - } else { - if (inBuffer.hasArray()) { - in = inBuffer.array(); - inOfs = inBuffer.position() + inBuffer.arrayOffset(); + NIO_ACCESS.acquireSession(outBuffer); + try { + try { + ensureInitialized(); + + long inAddr = 0; + byte[] in = null; + int inOfs = 0; + + if (dataBuffer.size() > 0) { + if (inBuffer != null && inLen > 0) { + byte[] temp = new byte[inLen]; + inBuffer.get(temp); + dataBuffer.write(temp, 0, temp.length); + } + + in = dataBuffer.toByteArray(); + inOfs = 0; + inLen = in.length; } else { - in = new byte[inLen]; - inBuffer.get(in); + if (inBuffer instanceof DirectBuffer dInBuffer) { + inAddr = dInBuffer.address(); + inOfs = inBuffer.position(); + } else { + if (inBuffer.hasArray()) { + in = inBuffer.array(); + inOfs = inBuffer.position() + inBuffer.arrayOffset(); + } else { + in = new byte[inLen]; + inBuffer.get(in); + } + } + } + long outAddr = 0; + byte[] outArray = null; + int outOfs = 0; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); + } else { + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = outBuffer.position() + outBuffer.arrayOffset(); + } else { + outArray = new byte[outLen]; + } } - } - } - long outAddr = 0; - byte[] outArray = null; - int outOfs = 0; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = outBuffer.position() + outBuffer.arrayOffset(); - } else { - outArray = new byte[outLen]; - } - } - if (opmode == Cipher.ENCRYPT_MODE) { - k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; - } else { - // Special handling to match SunJCE provider behavior - if (inLen == 0) { - return 0; + if (opmode == Cipher.ENCRYPT_MODE) { + k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } else { + // Special handling to match SunJCE provider behavior + if (inLen == 0) { + return 0; + } + k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } + inBuffer.position(inBuffer.limit()); + outBuffer.position(outBuffer.position() + k); + } catch (PKCS11Exception e) { + // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only + // keep the operation active on CKR_BUFFER_TOO_SMALL errors or + // successful calls to determine the output length. However, + // these cases are not expected here because the output length + // is checked in the OpenJDK side before making the PKCS#11 call. + // Thus, doCancel can safely be 'false'. + doCancel = false; + handleEncException("doFinal() failed", e); + } finally { + reset(doCancel); } - k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; + } finally { + NIO_ACCESS.releaseSession(outBuffer); } - inBuffer.position(inBuffer.limit()); - outBuffer.position(outBuffer.position() + k); - } catch (PKCS11Exception e) { - // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only - // keep the operation active on CKR_BUFFER_TOO_SMALL errors or - // successful calls to determine the output length. However, - // these cases are not expected here because the output length - // is checked in the OpenJDK side before making the PKCS#11 call. - // Thus, doCancel can safely be 'false'. - doCancel = false; - handleEncException("doFinal() failed", e); } finally { - reset(doCancel); + NIO_ACCESS.releaseSession(inBuffer); } return k; } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java index 54a1986f6a872..cbf40bd39b461 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java @@ -32,6 +32,8 @@ import javax.crypto.MacSpi; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.pkcs11.wrapper.*; @@ -55,6 +57,8 @@ */ final class P11Mac extends MacSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // token instance private final Token token; @@ -246,13 +250,17 @@ protected void engineUpdate(ByteBuffer byteBuffer) { if (len <= 0) { return; } - if (!(byteBuffer instanceof DirectBuffer directBuffer)) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { super.engineUpdate(byteBuffer); return; } - long addr = directBuffer.address(); int ofs = byteBuffer.position(); - token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len); + NIO_ACCESS.acquireSession(byteBuffer); + try { + token.p11.C_SignUpdate(session.id(), dByteBuffer.address() + ofs, null, 0, len); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); + } byteBuffer.position(ofs + len); } catch (PKCS11Exception e) { throw new ProviderException("update() failed", e); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java index e90a4d2a6da3f..b7df5fd352a66 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java @@ -25,13 +25,13 @@ package sun.security.pkcs11; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.nio.ByteBuffer; + +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import java.util.Hashtable; -import java.util.Arrays; import java.security.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.MGF1ParameterSpec; @@ -68,6 +68,8 @@ */ final class P11PSSSignature extends SignatureSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private static final boolean DEBUG = false; // mappings of digest algorithms and their output length in bytes @@ -613,14 +615,15 @@ protected void engineUpdate(ByteBuffer byteBuffer) { isActive = true; switch (type) { case T_UPDATE -> { - if (byteBuffer instanceof DirectBuffer == false) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { // cannot do better than default impl super.engineUpdate(byteBuffer); return; } - long addr = ((DirectBuffer) byteBuffer).address(); int ofs = byteBuffer.position(); + NIO_ACCESS.acquireSession(byteBuffer); try { + long addr = dByteBuffer.address(); if (mode == M_SIGN) { if (DEBUG) System.out.println(this + ": Calling C_SignUpdate"); token.p11.C_SignUpdate @@ -635,6 +638,8 @@ protected void engineUpdate(ByteBuffer byteBuffer) { } catch (PKCS11Exception e) { reset(false); throw new ProviderException("Update failed", e); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); } } case T_DIGEST -> { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java index e262d95c67fe9..23386daf29e09 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java @@ -32,10 +32,12 @@ import java.security.*; import java.security.interfaces.*; import java.security.spec.AlgorithmParameterSpec; + +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.util.*; -import sun.security.x509.AlgorithmId; import sun.security.rsa.RSAUtil; import sun.security.rsa.RSAPadding; @@ -98,6 +100,8 @@ */ final class P11Signature extends SignatureSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // token instance private final Token token; @@ -575,14 +579,15 @@ protected void engineUpdate(ByteBuffer byteBuffer) { } switch (type) { case T_UPDATE -> { - if (!(byteBuffer instanceof DirectBuffer)) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { // cannot do better than default impl super.engineUpdate(byteBuffer); return; } - long addr = ((DirectBuffer) byteBuffer).address(); int ofs = byteBuffer.position(); + NIO_ACCESS.acquireSession(byteBuffer); try { + long addr = dByteBuffer.address(); if (mode == M_SIGN) { token.p11.C_SignUpdate (session.id(), addr + ofs, null, 0, len); @@ -595,6 +600,8 @@ protected void engineUpdate(ByteBuffer byteBuffer) { } catch (PKCS11Exception e) { reset(false); throw new ProviderException("Update failed", e); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); } } case T_DIGEST -> { diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 348c9e8a6686d..6ad541b36a39b 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -53,6 +53,8 @@ import com.sun.nio.sctp.NotificationHandler; import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpSocketOption; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.net.util.IPAddressUtil; import sun.nio.ch.DirectBuffer; import sun.nio.ch.IOStatus; @@ -74,6 +76,9 @@ public class SctpChannelImpl extends SctpChannel implements SelChImpl { + + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private final FileDescriptor fd; private final int fdVal; @@ -839,11 +844,16 @@ private int receiveIntoNativeBuffer(int fd, boolean peek) throws IOException { - int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem, peek); + NIO_ACCESS.acquireSession(bb); + try { + int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem, peek); - if (n > 0) - bb.position(pos + n); - return n; + if (n > 0) + bb.position(pos + n); + return n; + } finally { + NIO_ACCESS.releaseSession(bb); + } } private InternalNotificationHandler internalNotificationHandler = @@ -1028,11 +1038,16 @@ private int sendFromNativeBuffer(int fd, assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, - port, -1 /*121*/, streamNumber, unordered, ppid); - if (written > 0) - bb.position(pos + written); - return written; + NIO_ACCESS.acquireSession(bb); + try { + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, -1 /*121*/, streamNumber, unordered, ppid); + if (written > 0) + bb.position(pos + written); + return written; + } finally { + NIO_ACCESS.releaseSession(bb); + } } @Override diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index ad708d0e71ba1..ca55e553e6a7f 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -53,6 +53,8 @@ import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpMultiChannel; import com.sun.nio.sctp.SctpSocketOption; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.net.util.IPAddressUtil; import sun.nio.ch.DirectBuffer; import sun.nio.ch.NativeThread; @@ -71,6 +73,8 @@ public class SctpMultiChannelImpl extends SctpMultiChannel implements SelChImpl { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private final FileDescriptor fd; private final int fdVal; @@ -583,10 +587,15 @@ private int receiveIntoNativeBuffer(int fd, int rem, int pos) throws IOException { - int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem); - if (n > 0) - bb.position(pos + n); - return n; + NIO_ACCESS.acquireSession(bb); + try { + int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem); + if (n > 0) + bb.position(pos + n); + return n; + } finally { + NIO_ACCESS.releaseSession(bb); + } } private InternalNotificationHandler internalNotificationHandler = @@ -908,11 +917,16 @@ private int sendFromNativeBuffer(int fd, assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, - port, assocId, streamNumber, unordered, ppid); - if (written > 0) - bb.position(pos + written); - return written; + NIO_ACCESS.acquireSession(bb); + try { + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, assocId, streamNumber, unordered, ppid); + if (written > 0) + bb.position(pos + written); + return written; + } finally { + NIO_ACCESS.releaseSession(bb); + } } @Override