This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch 2.1.X
in repository https://gitbox.apache.org/repos/asf/mina.git
The following commit(s) were added to refs/heads/2.1.X by this push:
new 3166d262d Applied the fix for the CVE-2026-47065 that wasn't back
ported by mistake. Also added a protection against concurrent access of the
selector
3166d262d is described below
commit 3166d262de1e7027a360ebb85732dbf861b1eea7
Author: emmanuel lecharny <[email protected]>
AuthorDate: Sat Jun 20 16:06:50 2026 +0200
Applied the fix for the CVE-2026-47065 that wasn't back ported by mistake.
Also added a protection against concurrent access of the selector
---
.../apache/mina/core/buffer/AbstractIoBuffer.java | 24 ++++++++++++++++++++
.../mina/transport/socket/nio/NioProcessor.java | 26 +++++++++++++++++++---
2 files changed, 47 insertions(+), 3 deletions(-)
diff --git
a/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
b/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
index f5aa45b99..2fb4cdf89 100644
--- a/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
+++ b/mina-core/src/main/java/org/apache/mina/core/buffer/AbstractIoBuffer.java
@@ -28,6 +28,7 @@ import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.StreamCorruptedException;
+import java.lang.reflect.Proxy;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
@@ -2213,6 +2214,29 @@ public abstract class AbstractIoBuffer extends IoBuffer {
return super.resolveClass(desc);
}
}
+
+ @Override
+ protected Class<?> resolveProxyClass(String[] interfaces) throws
IOException, ClassNotFoundException {
+ Class<?>[] classes = new Class<?>[interfaces.length];
+ int i = 0;
+
+ for (String interfaceName : interfaces) {
+ // Apply the acceptMatchers filter to EVERY proxy
interface name before
+ // any Class.forName() call. The JDK default
resolveProxyClass() bypasses
+ // resolveClass()/readClassDescriptor() entirely, so
without this override
+ // an attacker can deserialize a java.lang.reflect.Proxy
implementing
+ // arbitrary interfaces regardless of the configured
allow-list.
+ if (!acceptMatchers.stream().anyMatch(m ->
m.matches(interfaceName))) {
+ throw new ClassNotFoundException("Interface not in
accept list " + interfaceName);
+ }
+
+ // Use Class.forName(name, false, loader) -
initialize=false - and load via
+ // the configured classLoader, NOT
latestUserDefinedLoader().
+ classes[i++] = Class.forName(interfaceName, false,
classLoader);
+ }
+
+ return Proxy.getProxyClass(classLoader, classes);
+ }
}) {
return in.readObject();
} catch (IOException e) {
diff --git
a/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java
b/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java
index 1dc8d2efe..5a6385b46 100644
---
a/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java
+++
b/mina-core/src/main/java/org/apache/mina/transport/socket/nio/NioProcessor.java
@@ -163,7 +163,13 @@ public class NioProcessor extends
AbstractPollingIoProcessor<NioSession> {
@Override
protected int allSessionsCount()
{
- return selector.keys().size();
+ selectorLock.readLock().lock();
+
+ try {
+ return selector.keys().size();
+ } finally {
+ selectorLock.readLock().unlock();
+ }
}
@SuppressWarnings("synthetic-access")
@@ -345,7 +351,14 @@ public class NioProcessor extends
AbstractPollingIoProcessor<NioSession> {
}
if (oldInterestOps != newInterestOps) {
- key.interestOps(newInterestOps);
+ // Protect the selector against concurrent accesses
+ selectorLock.readLock().lock();
+
+ try {
+ key.interestOps(newInterestOps);
+ } finally {
+ selectorLock.readLock().unlock();
+ }
}
}
@@ -368,7 +381,14 @@ public class NioProcessor extends
AbstractPollingIoProcessor<NioSession> {
newInterestOps &= ~SelectionKey.OP_WRITE;
}
- key.interestOps(newInterestOps);
+ // Protect the selector against concurrent accesses
+ selectorLock.readLock().lock();
+
+ try {
+ key.interestOps(newInterestOps);
+ } finally {
+ selectorLock.readLock().unlock();
+ }
}
@Override