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

View File

@ -37,6 +37,7 @@ import jdk.internal.vm.annotation.ForceInline;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.lang.foreign.MemorySegment; import java.lang.foreign.MemorySegment;
import java.lang.ref.Reference;
import java.util.Objects; import java.util.Objects;
import java.util.Spliterator; import java.util.Spliterator;
@ -779,6 +780,7 @@ public abstract sealed class Buffer
// setup access to this package in SharedSecrets // setup access to this package in SharedSecrets
SharedSecrets.setJavaNioAccess( SharedSecrets.setJavaNioAccess(
new JavaNioAccess() { new JavaNioAccess() {
@Override @Override
public BufferPool getDirectBufferPool() { public BufferPool getDirectBufferPool() {
return Bits.BUFFER_POOL; return Bits.BUFFER_POOL;
@ -824,16 +826,34 @@ public abstract sealed class Buffer
} }
@Override @Override
public Runnable acquireSession(Buffer buffer, boolean async) { public void acquireSession(Buffer buffer) {
var session = buffer.session(); var scope = buffer.session();
if (session == null) { if (scope != null) {
return 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 @Override

View File

@ -25,11 +25,13 @@
package java.util.zip; package java.util.zip;
import java.lang.ref.Reference;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import sun.nio.ch.DirectBuffer;
import jdk.internal.util.Preconditions; import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.IntrinsicCandidate; 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 * 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) if (rem <= 0)
return; return;
if (buffer.isDirect()) { if (buffer.isDirect()) {
NIO_ACCESS.acquireSession(buffer);
try { try {
adler = updateByteBuffer(adler, ((DirectBuffer)buffer).address(), pos, rem); adler = updateByteBuffer(adler, ((DirectBuffer)buffer).address(), pos, rem);
} finally { } finally {
Reference.reachabilityFence(buffer); NIO_ACCESS.releaseSession(buffer);
} }
} else if (buffer.hasArray()) { } else if (buffer.hasArray()) {
adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem); adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem);

View File

@ -25,7 +25,6 @@
package java.util.zip; package java.util.zip;
import java.lang.ref.Reference;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Objects; import java.util.Objects;
@ -33,6 +32,8 @@ import sun.nio.ch.DirectBuffer;
import jdk.internal.util.Preconditions; import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.IntrinsicCandidate; 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. * 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) if (rem <= 0)
return; return;
if (buffer.isDirect()) { if (buffer.isDirect()) {
NIO_ACCESS.acquireSession(buffer);
try { try {
crc = updateByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, rem); crc = updateByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, rem);
} finally { } finally {
Reference.reachabilityFence(buffer); NIO_ACCESS.releaseSession(buffer);
} }
} else if (buffer.hasArray()) { } else if (buffer.hasArray()) {
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem); crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem);

View File

@ -24,7 +24,6 @@
*/ */
package java.util.zip; package java.util.zip;
import java.lang.ref.Reference;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
@ -33,6 +32,8 @@ import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.IntrinsicCandidate;
import sun.nio.ch.DirectBuffer; 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. * 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()) { if (buffer.isDirect()) {
NIO_ACCESS.acquireSession(buffer);
try { try {
crc = updateDirectByteBuffer(crc, ((DirectBuffer) buffer).address(), crc = updateDirectByteBuffer(crc, ((DirectBuffer)buffer).address(),
pos, limit); pos, limit);
} finally { } finally {
Reference.reachabilityFence(buffer); NIO_ACCESS.releaseSession(buffer);
} }
} else if (buffer.hasArray()) { } else if (buffer.hasArray()) {
crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(),

View File

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

View File

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

View File

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

View File

@ -86,12 +86,26 @@ public interface JavaNioAccess {
MemorySegment bufferSegment(Buffer buffer); MemorySegment bufferSegment(Buffer buffer);
/** /**
* Used by I/O operations to make a buffer's session non-closeable * Used by operations to make a buffer's session non-closeable
* (for the duration of the I/O operation) by acquiring the session. * (for the duration of the operation) by acquiring the session.
* Null is returned if the buffer has no scope, or acquiring is not * {@snippet lang = java:
* required to guarantee safety. * 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. * 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.jartool,
jdk.jlink, jdk.jlink,
jdk.jfr, jdk.jfr,
jdk.net; jdk.net,
jdk.sctp,
jdk.crypto.cryptoki;
exports jdk.internal.foreign to exports jdk.internal.foreign to
jdk.incubator.vector; jdk.incubator.vector;
exports jdk.internal.event to 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.concurrent.locks.ReentrantLock;
import java.util.function.Consumer; import java.util.function.Consumer;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.ref.CleanerFactory; import jdk.internal.ref.CleanerFactory;
import sun.net.ResourceManager; import sun.net.ResourceManager;
import sun.net.ext.ExtendedSocketOptions; import sun.net.ext.ExtendedSocketOptions;
@ -87,6 +89,8 @@ class DatagramChannelImpl
// Used to make native read and write calls // Used to make native read and write calls
private static final NativeDispatcher nd = new DatagramDispatcher(); 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) // true if interruptible (can be false to emulate legacy DatagramSocket)
private final boolean interruptible; private final boolean interruptible;
@ -780,13 +784,18 @@ class DatagramChannelImpl
boolean connected) boolean connected)
throws IOException throws IOException
{ {
int n = receive0(fd, NIO_ACCESS.acquireSession(bb);
((DirectBuffer)bb).address() + pos, rem, try {
sourceSockAddr.address(), int n = receive0(fd,
connected); ((DirectBuffer)bb).address() + pos, rem,
if (n > 0) sourceSockAddr.address(),
bb.position(pos + n); connected);
return n; 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 rem = (pos <= lim ? lim - pos : 0);
int written; int written;
NIO_ACCESS.acquireSession(bb);
try { try {
int addressLen = targetSocketAddress(target); int addressLen = targetSocketAddress(target);
written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, written = send0(fd, ((DirectBuffer)bb).address() + pos, rem,
@ -938,6 +948,8 @@ class DatagramChannelImpl
if (isConnected()) if (isConnected())
throw pue; throw pue;
written = rem; written = rem;
} finally {
NIO_ACCESS.releaseSession(bb);
} }
if (written > 0) if (written > 0)
bb.position(pos + written); bb.position(pos + written);

View File

@ -30,6 +30,13 @@ import jdk.internal.ref.Cleaner;
public interface DirectBuffer { 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 long address();
public Object attachment(); public Object attachment();

View File

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

View File

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

View File

@ -25,11 +25,13 @@
package sun.nio.fs; package sun.nio.fs;
import java.lang.ref.Reference;
import java.nio.file.*; import java.nio.file.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Unsafe; import jdk.internal.misc.Unsafe;
import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixConstants.*;
@ -43,6 +45,8 @@ abstract class UnixUserDefinedFileAttributeView
{ {
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// namespace for extended user attributes // namespace for extended user attributes
private static final String USER_NAMESPACE = "user."; private static final String USER_NAMESPACE = "user.";
@ -174,14 +178,15 @@ abstract class UnixUserDefinedFileAttributeView
assert (pos <= lim); assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0); 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 { try {
long address = buf.address() + pos; long address = ddst.address() + pos;
int n = read(name, address, rem); int n = read(name, address, rem);
dst.position(pos + n); dst.position(pos + n);
return n; return n;
} finally { } finally {
Reference.reachabilityFence(buf); NIO_ACCESS.releaseSession(dst);
} }
} else { } else {
try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) { try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) {
@ -237,13 +242,14 @@ abstract class UnixUserDefinedFileAttributeView
int rem = (pos <= lim ? lim - pos : 0); int rem = (pos <= lim ? lim - pos : 0);
if (src instanceof sun.nio.ch.DirectBuffer buf) { if (src instanceof sun.nio.ch.DirectBuffer buf) {
NIO_ACCESS.acquireSession(src);
try { try {
long address = buf.address() + pos; long address = buf.address() + pos;
write(name, address, rem); write(name, address, rem);
src.position(pos + rem); src.position(pos + rem);
return rem; return rem;
} finally { } finally {
Reference.reachabilityFence(buf); NIO_ACCESS.releaseSession(src);
} }
} else { } else {
try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) { try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) {

View File

@ -35,6 +35,8 @@ import java.security.spec.*;
import javax.crypto.*; import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
@ -55,6 +57,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
*/ */
final class P11AEADCipher extends CipherSpi { final class P11AEADCipher extends CipherSpi {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// supported AEAD algorithms/transformations // supported AEAD algorithms/transformations
private enum Transformation { private enum Transformation {
AES_GCM("AES", "GCM", "NOPADDING", 16, 16), AES_GCM("AES", "GCM", "NOPADDING", 16, 16),
@ -705,84 +709,94 @@ final class P11AEADCipher extends CipherSpi {
} }
boolean doCancel = true; boolean doCancel = true;
NIO_ACCESS.acquireSession(inBuffer);
try { try {
ensureInitialized(); NIO_ACCESS.acquireSession(outBuffer);
try {
try {
ensureInitialized();
long inAddr = 0; long inAddr = 0;
byte[] in = null; byte[] in = null;
int inOfs = 0; int inOfs = 0;
if (dataBuffer.size() > 0) { if (dataBuffer.size() > 0) {
if (inLen > 0) { if (inLen > 0) {
byte[] temp = new byte[inLen]; byte[] temp = new byte[inLen];
inBuffer.get(temp); inBuffer.get(temp);
dataBuffer.write(temp, 0, temp.length); dataBuffer.write(temp, 0, temp.length);
} }
in = dataBuffer.toByteArray(); in = dataBuffer.toByteArray();
inOfs = 0; inOfs = 0;
inLen = in.length; 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();
} else { } else {
in = new byte[inLen]; if (inBuffer instanceof DirectBuffer dInBuffer) {
inBuffer.get(in); 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; int k = 0;
if (encrypt) { if (encrypt) {
k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen,
outAddr, outArray, outOfs, outLen); outAddr, outArray, outOfs, outLen);
doCancel = false; doCancel = false;
} else { } else {
// Special handling to match SunJCE provider behavior // Special handling to match SunJCE provider behavior
if (inLen == 0) { if (inLen == 0) {
return 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, } finally {
outAddr, outArray, outOfs, outLen); NIO_ACCESS.releaseSession(outBuffer);
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 { } finally {
if (encrypt) { NIO_ACCESS.releaseSession(inBuffer);
lastEncKey = this.p11Key;
lastEncIv = this.iv;
requireReinit = true;
}
reset(doCancel);
} }
} }

View File

@ -34,6 +34,8 @@ import java.security.spec.*;
import javax.crypto.*; import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
@ -56,6 +58,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
*/ */
final class P11Cipher extends CipherSpi { final class P11Cipher extends CipherSpi {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// mode constant for ECB mode // mode constant for ECB mode
private static final int MODE_ECB = 3; private static final int MODE_ECB = 3;
// mode constant for CBC mode // mode constant for CBC mode
@ -678,115 +682,123 @@ final class P11Cipher extends CipherSpi {
throw new ShortBufferException(); throw new ShortBufferException();
} }
int origPos = inBuffer.position(); int origPos = inBuffer.position();
NIO_ACCESS.acquireSession(inBuffer);
try { try {
ensureInitialized(); NIO_ACCESS.acquireSession(outBuffer);
try {
ensureInitialized();
long inAddr = 0; long inAddr = 0;
int inOfs = 0; int inOfs = 0;
byte[] inArray = null; byte[] inArray = null;
if (inBuffer instanceof DirectBuffer) { if (inBuffer instanceof DirectBuffer dInBuffer) {
inAddr = ((DirectBuffer) inBuffer).address(); inAddr = dInBuffer.address();
inOfs = origPos; inOfs = origPos;
} else if (inBuffer.hasArray()) { } else if (inBuffer.hasArray()) {
inArray = inBuffer.array(); inArray = inBuffer.array();
inOfs = (origPos + inBuffer.arrayOffset()); 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());
} else {
outArray = new byte[outLen];
} }
}
int k = 0; long outAddr = 0;
int newPadBufferLen = 0; int outOfs = 0;
if (paddingObj != null && (!encrypt || reqBlockUpdates)) { byte[] outArray = null;
if (padBufferLen != 0) { if (outBuffer instanceof DirectBuffer dOutBuffer) {
if (padBufferLen != padBuffer.length) { outAddr = dOutBuffer.address();
int bufCapacity = padBuffer.length - padBufferLen; outOfs = outBuffer.position();
if (inLen > bufCapacity) { } else {
bufferInputBytes(inBuffer, bufCapacity); if (outBuffer.hasArray()) {
inOfs += bufCapacity; outArray = outBuffer.array();
inLen -= bufCapacity; outOfs = (outBuffer.position() + outBuffer.arrayOffset());
} else { } else {
bufferInputBytes(inBuffer, inLen); outArray = new byte[outLen];
return 0; }
}
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 {
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) { if (encrypt) {
k = token.p11.C_EncryptUpdate(session.id(), 0, k += token.p11.C_EncryptUpdate(session.id(), inAddr,
padBuffer, 0, padBufferLen, outAddr, outArray, inArray, inOfs, inLen, outAddr, outArray,
outOfs, outLen); (outOfs + k), (outLen - k));
} else { } else {
k = token.p11.C_DecryptUpdate(session.id(), 0, k += token.p11.C_DecryptUpdate(session.id(), inAddr,
padBuffer, 0, padBufferLen, outAddr, outArray, inArray, inOfs, inLen, outAddr, outArray,
outOfs, outLen); (outOfs + k), (outLen - k));
} }
padBufferLen = 0;
} }
newPadBufferLen = inLen & (blockSize - 1); // update 'padBuffer' if using our own padding impl.
if (!encrypt && newPadBufferLen == 0) { if (paddingObj != null && newPadBufferLen > 0) {
// While decrypting with implUpdate, the last encrypted block bufferInputBytes(inBuffer, newPadBufferLen);
// 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; bytesBuffered += (inLen - k);
} if (!(outBuffer instanceof DirectBuffer) &&
if (inLen > 0) { !outBuffer.hasArray()) {
if (inAddr == 0 && inArray == null) { outBuffer.put(outArray, outOfs, k);
inArray = new byte[inLen];
inBuffer.get(inArray);
} else { } else {
inBuffer.position(inBuffer.position() + inLen); outBuffer.position(outBuffer.position() + k);
} }
if (encrypt) { return k;
k += token.p11.C_EncryptUpdate(session.id(), inAddr, } catch (PKCS11Exception e) {
inArray, inOfs, inLen, outAddr, outArray, // Reset input buffer to its original position for
(outOfs + k), (outLen - k)); inBuffer.position(origPos);
} else { if (e.match(CKR_BUFFER_TOO_SMALL)) {
k += token.p11.C_DecryptUpdate(session.id(), inAddr, throw (ShortBufferException)
inArray, inOfs, inLen, outAddr, outArray, (new ShortBufferException().initCause(e));
(outOfs + k), (outLen - k));
} }
// 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. } finally {
if (paddingObj != null && newPadBufferLen > 0) { NIO_ACCESS.releaseSession(inBuffer);
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);
} }
} }
@ -877,99 +889,104 @@ final class P11Cipher extends CipherSpi {
} }
boolean doCancel = true; boolean doCancel = true;
NIO_ACCESS.acquireSession(outBuffer);
try { try {
ensureInitialized(); try {
ensureInitialized();
long outAddr = 0; long outAddr = 0;
byte[] outArray = null; byte[] outArray = null;
int outOfs = 0; int outOfs = 0;
if (outBuffer instanceof DirectBuffer) { if (outBuffer instanceof DirectBuffer dOutBuffer) {
outAddr = ((DirectBuffer) outBuffer).address(); outAddr = dOutBuffer.address();
outOfs = outBuffer.position(); outOfs = outBuffer.position();
} else {
if (outBuffer.hasArray()) {
outArray = outBuffer.array();
outOfs = outBuffer.position() + outBuffer.arrayOffset();
} else { } else {
outArray = new byte[outLen]; if (outBuffer.hasArray()) {
} outArray = outBuffer.array();
} outOfs = outBuffer.position() + outBuffer.arrayOffset();
} else {
int k = 0; outArray = new byte[outLen];
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) { int k = 0;
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(), if (encrypt) {
0, padBuffer, 0, padBufferLen, if (paddingObj != null) {
0, padBuffer, 0, padBuffer.length); int startOff = 0;
padBufferLen = 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 // 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 // required by the PKCS#11 standard). Cancel is not needed
// only after this point. See JDK-8258833 for further // only after this point. See JDK-8258833 for further
// information. // information.
doCancel = false; doCancel = false;
k += token.p11.C_DecryptFinal(session.id(), k += token.p11.C_EncryptFinal(session.id(),
0, padBuffer, k, padBuffer.length - k); outAddr, outArray, (outOfs + k), (outLen - k));
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
outArray = padBuffer;
outOfs = 0;
} else { } else {
doCancel = false; // Special handling to match SunJCE provider behavior
k = token.p11.C_DecryptFinal(session.id(), if (bytesBuffered == 0 && padBufferLen == 0) {
outAddr, outArray, outOfs, outLen); 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;
}
// 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 {
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 { } finally {
reset(doCancel); NIO_ACCESS.releaseSession(outBuffer);
} }
} }

View File

@ -25,13 +25,14 @@
package sun.security.pkcs11; package sun.security.pkcs11;
import java.util.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.*; import java.security.*;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.security.util.MessageDigestSpi2; import sun.security.util.MessageDigestSpi2;
@ -55,6 +56,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
final class P11Digest extends MessageDigestSpi implements Cloneable, final class P11Digest extends MessageDigestSpi implements Cloneable,
MessageDigestSpi2 { MessageDigestSpi2 {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
/* fields initialized, no session acquired */ /* fields initialized, no session acquired */
private static final int S_BLANK = 1; private static final int S_BLANK = 1;
@ -268,13 +271,12 @@ final class P11Digest extends MessageDigestSpi implements Cloneable,
return; return;
} }
if (!(byteBuffer instanceof DirectBuffer)) { if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) {
super.engineUpdate(byteBuffer); super.engineUpdate(byteBuffer);
return; return;
} }
fetchSession(); fetchSession();
long addr = ((DirectBuffer)byteBuffer).address();
int ofs = byteBuffer.position(); int ofs = byteBuffer.position();
try { try {
if (state == S_BUFFERED) { if (state == S_BUFFERED) {
@ -285,7 +287,12 @@ final class P11Digest extends MessageDigestSpi implements Cloneable,
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs); token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
bufOfs = 0; 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); byteBuffer.position(ofs + len);
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
engineReset(); engineReset();

View File

@ -37,13 +37,14 @@ import javax.crypto.spec.*;
import java.util.HexFormat; import java.util.HexFormat;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
import static sun.security.pkcs11.TemplateManager.*; import static sun.security.pkcs11.TemplateManager.*;
import static sun.security.pkcs11.P11Cipher.*;
/** /**
* P11 KeyWrap Cipher implementation class for native impl which only support * P11 KeyWrap Cipher implementation class for native impl which only support
@ -58,6 +59,8 @@ import static sun.security.pkcs11.P11Cipher.*;
*/ */
final class P11KeyWrapCipher extends CipherSpi { final class P11KeyWrapCipher extends CipherSpi {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
private static final int BLK_SIZE = 8; private static final int BLK_SIZE = 8;
// supported mode and padding with AES cipher // supported mode and padding with AES cipher
@ -552,78 +555,88 @@ final class P11KeyWrapCipher extends CipherSpi {
boolean doCancel = true; boolean doCancel = true;
int k = 0; int k = 0;
NIO_ACCESS.acquireSession(inBuffer);
try { try {
ensureInitialized(); NIO_ACCESS.acquireSession(outBuffer);
try {
try {
ensureInitialized();
long inAddr = 0; long inAddr = 0;
byte[] in = null; byte[] in = null;
int inOfs = 0; int inOfs = 0;
if (dataBuffer.size() > 0) { if (dataBuffer.size() > 0) {
if (inBuffer != null && inLen > 0) { if (inBuffer != null && inLen > 0) {
byte[] temp = new byte[inLen]; byte[] temp = new byte[inLen];
inBuffer.get(temp); inBuffer.get(temp);
dataBuffer.write(temp, 0, temp.length); dataBuffer.write(temp, 0, temp.length);
} }
in = dataBuffer.toByteArray(); in = dataBuffer.toByteArray();
inOfs = 0; inOfs = 0;
inLen = in.length; 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();
} else { } else {
in = new byte[inLen]; if (inBuffer instanceof DirectBuffer dInBuffer) {
inBuffer.get(in); 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) { if (opmode == Cipher.ENCRYPT_MODE) {
k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen,
outAddr, outArray, outOfs, outLen); outAddr, outArray, outOfs, outLen);
doCancel = false; doCancel = false;
} else { } else {
// Special handling to match SunJCE provider behavior // Special handling to match SunJCE provider behavior
if (inLen == 0) { if (inLen == 0) {
return 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, } finally {
outAddr, outArray, outOfs, outLen); NIO_ACCESS.releaseSession(outBuffer);
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 { } finally {
reset(doCancel); NIO_ACCESS.releaseSession(inBuffer);
} }
return k; return k;
} }

View File

@ -32,6 +32,8 @@ import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.MacSpi; import javax.crypto.MacSpi;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
@ -55,6 +57,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
*/ */
final class P11Mac extends MacSpi { final class P11Mac extends MacSpi {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// token instance // token instance
private final Token token; private final Token token;
@ -246,13 +250,17 @@ final class P11Mac extends MacSpi {
if (len <= 0) { if (len <= 0) {
return; return;
} }
if (!(byteBuffer instanceof DirectBuffer directBuffer)) { if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) {
super.engineUpdate(byteBuffer); super.engineUpdate(byteBuffer);
return; return;
} }
long addr = directBuffer.address();
int ofs = byteBuffer.position(); 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); byteBuffer.position(ofs + len);
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
throw new ProviderException("update() failed", e); throw new ProviderException("update() failed", e);

View File

@ -25,13 +25,13 @@
package sun.security.pkcs11; package sun.security.pkcs11;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Arrays;
import java.security.*; import java.security.*;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec; import java.security.spec.MGF1ParameterSpec;
@ -68,6 +68,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
*/ */
final class P11PSSSignature extends SignatureSpi { final class P11PSSSignature extends SignatureSpi {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
// mappings of digest algorithms and their output length in bytes // mappings of digest algorithms and their output length in bytes
@ -613,14 +615,15 @@ final class P11PSSSignature extends SignatureSpi {
isActive = true; isActive = true;
switch (type) { switch (type) {
case T_UPDATE -> { case T_UPDATE -> {
if (byteBuffer instanceof DirectBuffer == false) { if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) {
// cannot do better than default impl // cannot do better than default impl
super.engineUpdate(byteBuffer); super.engineUpdate(byteBuffer);
return; return;
} }
long addr = ((DirectBuffer) byteBuffer).address();
int ofs = byteBuffer.position(); int ofs = byteBuffer.position();
NIO_ACCESS.acquireSession(byteBuffer);
try { try {
long addr = dByteBuffer.address();
if (mode == M_SIGN) { if (mode == M_SIGN) {
if (DEBUG) System.out.println(this + ": Calling C_SignUpdate"); if (DEBUG) System.out.println(this + ": Calling C_SignUpdate");
token.p11.C_SignUpdate token.p11.C_SignUpdate
@ -635,6 +638,8 @@ final class P11PSSSignature extends SignatureSpi {
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
reset(false); reset(false);
throw new ProviderException("Update failed", e); throw new ProviderException("Update failed", e);
} finally {
NIO_ACCESS.releaseSession(byteBuffer);
} }
} }
case T_DIGEST -> { case T_DIGEST -> {

View File

@ -32,10 +32,12 @@ import java.nio.ByteBuffer;
import java.security.*; import java.security.*;
import java.security.interfaces.*; import java.security.interfaces.*;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.security.util.*; import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.rsa.RSAUtil; import sun.security.rsa.RSAUtil;
import sun.security.rsa.RSAPadding; import sun.security.rsa.RSAPadding;
@ -98,6 +100,8 @@ import sun.security.util.KeyUtil;
*/ */
final class P11Signature extends SignatureSpi { final class P11Signature extends SignatureSpi {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
// token instance // token instance
private final Token token; private final Token token;
@ -575,14 +579,15 @@ final class P11Signature extends SignatureSpi {
} }
switch (type) { switch (type) {
case T_UPDATE -> { case T_UPDATE -> {
if (!(byteBuffer instanceof DirectBuffer)) { if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) {
// cannot do better than default impl // cannot do better than default impl
super.engineUpdate(byteBuffer); super.engineUpdate(byteBuffer);
return; return;
} }
long addr = ((DirectBuffer) byteBuffer).address();
int ofs = byteBuffer.position(); int ofs = byteBuffer.position();
NIO_ACCESS.acquireSession(byteBuffer);
try { try {
long addr = dByteBuffer.address();
if (mode == M_SIGN) { if (mode == M_SIGN) {
token.p11.C_SignUpdate token.p11.C_SignUpdate
(session.id(), addr + ofs, null, 0, len); (session.id(), addr + ofs, null, 0, len);
@ -595,6 +600,8 @@ final class P11Signature extends SignatureSpi {
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
reset(false); reset(false);
throw new ProviderException("Update failed", e); throw new ProviderException("Update failed", e);
} finally {
NIO_ACCESS.releaseSession(byteBuffer);
} }
} }
case T_DIGEST -> { case T_DIGEST -> {

View File

@ -53,6 +53,8 @@ import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.NotificationHandler; import com.sun.nio.sctp.NotificationHandler;
import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpSocketOption; import com.sun.nio.sctp.SctpSocketOption;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.net.util.IPAddressUtil; import sun.net.util.IPAddressUtil;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.nio.ch.IOStatus; import sun.nio.ch.IOStatus;
@ -74,6 +76,9 @@ import static sun.nio.ch.sctp.ResultContainer.SHUTDOWN;
public class SctpChannelImpl extends SctpChannel public class SctpChannelImpl extends SctpChannel
implements SelChImpl implements SelChImpl
{ {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
private final FileDescriptor fd; private final FileDescriptor fd;
private final int fdVal; private final int fdVal;
@ -839,11 +844,16 @@ public class SctpChannelImpl extends SctpChannel
boolean peek) boolean peek)
throws IOException 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) if (n > 0)
bb.position(pos + n); bb.position(pos + n);
return n; return n;
} finally {
NIO_ACCESS.releaseSession(bb);
}
} }
private InternalNotificationHandler internalNotificationHandler = private InternalNotificationHandler internalNotificationHandler =
@ -1028,11 +1038,16 @@ public class SctpChannelImpl extends SctpChannel
assert (pos <= lim); assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0); int rem = (pos <= lim ? lim - pos : 0);
int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, NIO_ACCESS.acquireSession(bb);
port, -1 /*121*/, streamNumber, unordered, ppid); try {
if (written > 0) int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr,
bb.position(pos + written); port, -1 /*121*/, streamNumber, unordered, ppid);
return written; if (written > 0)
bb.position(pos + written);
return written;
} finally {
NIO_ACCESS.releaseSession(bb);
}
} }
@Override @Override

View File

@ -53,6 +53,8 @@ import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpMultiChannel; import com.sun.nio.sctp.SctpMultiChannel;
import com.sun.nio.sctp.SctpSocketOption; import com.sun.nio.sctp.SctpSocketOption;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import sun.net.util.IPAddressUtil; import sun.net.util.IPAddressUtil;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;
import sun.nio.ch.NativeThread; import sun.nio.ch.NativeThread;
@ -71,6 +73,8 @@ import static sun.nio.ch.sctp.ResultContainer.*;
public class SctpMultiChannelImpl extends SctpMultiChannel public class SctpMultiChannelImpl extends SctpMultiChannel
implements SelChImpl implements SelChImpl
{ {
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
private final FileDescriptor fd; private final FileDescriptor fd;
private final int fdVal; private final int fdVal;
@ -583,10 +587,15 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
int rem, int rem,
int pos) int pos)
throws IOException { throws IOException {
int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem); NIO_ACCESS.acquireSession(bb);
if (n > 0) try {
bb.position(pos + n); int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem);
return n; if (n > 0)
bb.position(pos + n);
return n;
} finally {
NIO_ACCESS.releaseSession(bb);
}
} }
private InternalNotificationHandler internalNotificationHandler = private InternalNotificationHandler internalNotificationHandler =
@ -908,11 +917,16 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
assert (pos <= lim); assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0); int rem = (pos <= lim ? lim - pos : 0);
int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, NIO_ACCESS.acquireSession(bb);
port, assocId, streamNumber, unordered, ppid); try {
if (written > 0) int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr,
bb.position(pos + written); port, assocId, streamNumber, unordered, ppid);
return written; if (written > 0)
bb.position(pos + written);
return written;
} finally {
NIO_ACCESS.releaseSession(bb);
}
} }
@Override @Override