Fix CVE-2023-5685
This commit is contained in:
parent
efda39b5ff
commit
739fb53300
364
backport-CVE-2023-5685.patch
Normal file
364
backport-CVE-2023-5685.patch
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
From a2fce38d48cca947ea42ee3bead08dd138b42c01 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Flavia Rainone <frainone@redhat.com>
|
||||||
|
Date: Fri, 14 Oct 2022 17:00:46 -0300
|
||||||
|
Subject: [PATCH] [XNIO-423] CVE-2023-5685 Move the recursion in NotifierState
|
||||||
|
to a iteration, preventing a stack overflow exception when the chain of
|
||||||
|
notifier states becomes problematically big
|
||||||
|
|
||||||
|
Signed-off-by: Flavia Rainone <frainone@redhat.com>
|
||||||
|
|
||||||
|
Origin:
|
||||||
|
https://github.com/xnio/xnio/commit/a2fce38d48cca947ea42ee3bead08dd138b42c01
|
||||||
|
---
|
||||||
|
.../main/java/org/xnio/AbstractIoFuture.java | 238 ++++++++++++++----
|
||||||
|
1 file changed, 187 insertions(+), 51 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/api/src/main/java/org/xnio/AbstractIoFuture.java b/api/src/main/java/org/xnio/AbstractIoFuture.java
|
||||||
|
index 6118a0c7e3..030336b918 100644
|
||||||
|
--- a/api/src/main/java/org/xnio/AbstractIoFuture.java
|
||||||
|
+++ b/api/src/main/java/org/xnio/AbstractIoFuture.java
|
||||||
|
@@ -74,6 +74,141 @@ IOException getException() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ private static abstract class NestedState<T> extends State<T> {
|
||||||
|
+ private final State<T> next;
|
||||||
|
+
|
||||||
|
+ public NestedState(final State next) {
|
||||||
|
+ this.next = next;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Perform any actions that need to be executed when future is done, delegation of done notification to next is
|
||||||
|
+ * taken care of by invoker.
|
||||||
|
+ *
|
||||||
|
+ * @param future the future
|
||||||
|
+ * @param result the result
|
||||||
|
+ */
|
||||||
|
+ protected abstract void doNotifyDone(AbstractIoFuture<T> future, T result);
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void notifyDone(AbstractIoFuture<T> future, T result) {
|
||||||
|
+ doNotifyDone(future, result);
|
||||||
|
+ if (next instanceof NestedState) {
|
||||||
|
+ NestedState<T> current = this;
|
||||||
|
+ do {
|
||||||
|
+ current = (NestedState<T>) current.next;
|
||||||
|
+ current.doNotifyDone(future, result);
|
||||||
|
+ } while (current.next instanceof NestedState);
|
||||||
|
+ current.next.notifyDone(future, result);
|
||||||
|
+ } else {
|
||||||
|
+ next.notifyDone(future, result);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Perform any actions that need to be done at this state for handling failure, delegation of failure
|
||||||
|
+ * notification to next is taken care of by invoker
|
||||||
|
+ *
|
||||||
|
+ * @param future the future
|
||||||
|
+ * @param exception the failure
|
||||||
|
+ */
|
||||||
|
+ protected abstract void doNotifyFailed(AbstractIoFuture<T> future, IOException exception);
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void notifyFailed(AbstractIoFuture<T> future, IOException exception) {
|
||||||
|
+ doNotifyFailed(future, exception);
|
||||||
|
+ if (next instanceof NestedState) {
|
||||||
|
+ NestedState<T> current = this;
|
||||||
|
+ do {
|
||||||
|
+ current = (NestedState<T>) current.next;
|
||||||
|
+ current.doNotifyFailed(future, exception);
|
||||||
|
+ } while (current.next instanceof NestedState);
|
||||||
|
+ current.next.notifyFailed(future, exception);
|
||||||
|
+ } else {
|
||||||
|
+ next.notifyFailed(future, exception);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Perform any actions that need to be done at this state for handling cancellation, delegation of cancellation
|
||||||
|
+ * notification to next is taken care of by invoker
|
||||||
|
+ *
|
||||||
|
+ * @param future the future
|
||||||
|
+ */
|
||||||
|
+ protected abstract void doNotifyCancelled(AbstractIoFuture<T> future);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public void notifyCancelled(AbstractIoFuture<T> future) {
|
||||||
|
+ doNotifyCancelled(future);
|
||||||
|
+ if (next instanceof NestedState) {
|
||||||
|
+ NestedState<T> current = this;
|
||||||
|
+ do {
|
||||||
|
+ current = (NestedState<T>) current.next;
|
||||||
|
+ current.doNotifyCancelled(future);
|
||||||
|
+ } while (current.next instanceof NestedState);
|
||||||
|
+ current.next.notifyCancelled(future);
|
||||||
|
+ } else {
|
||||||
|
+ next.notifyCancelled(future);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Perform any actions that need to be done at this state for cancellation. Delegation of cancellation to next
|
||||||
|
+ * is taken care of by invoker.
|
||||||
|
+ */
|
||||||
|
+ protected abstract void doCancel();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Just delegate cancel() to first next state in the nested chain that is not a NestedState.
|
||||||
|
+ */
|
||||||
|
+ @Override
|
||||||
|
+ public void cancel() {
|
||||||
|
+ doCancel();
|
||||||
|
+ if (next instanceof NestedState) {
|
||||||
|
+ NestedState<T> current = this;
|
||||||
|
+ do {
|
||||||
|
+ current = (NestedState<T>) current.next;
|
||||||
|
+ current.doCancel();
|
||||||
|
+ } while (current.next instanceof NestedState);
|
||||||
|
+ current.next.cancel();
|
||||||
|
+ } else {
|
||||||
|
+ next.cancel();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Return {@code true} to indicate that, at this state, cancel is requested. If returns false, invoker
|
||||||
|
+ * will check for inner next states in the chain until it finds a positive result or the final state in the
|
||||||
|
+ * chain.
|
||||||
|
+ *
|
||||||
|
+ * @return {@code true} to indicate that cancel is requested; {@code false} to delegate response to nested
|
||||||
|
+ * state.
|
||||||
|
+ */
|
||||||
|
+ protected abstract boolean isCancelRequested();
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean cancelRequested() {
|
||||||
|
+ if (isCancelRequested()) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (next instanceof NestedState) {
|
||||||
|
+ NestedState<T> current = this;
|
||||||
|
+ do {
|
||||||
|
+ current = (NestedState<T>) current.next;
|
||||||
|
+ if (current.isCancelRequested()) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ } while (current.next instanceof NestedState);
|
||||||
|
+ return current.next.cancelRequested();
|
||||||
|
+ } else {
|
||||||
|
+ return next.cancelRequested();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
static final class InitialState<T> extends State<T> {
|
||||||
|
|
||||||
|
Status getStatus() {
|
||||||
|
@@ -229,13 +364,12 @@ boolean cancelRequested() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- static final class NotifierState<T, A> extends State<T> {
|
||||||
|
- final State<T> next;
|
||||||
|
+ static final class NotifierState<T, A> extends NestedState<T> {
|
||||||
|
final Notifier<? super T, A> notifier;
|
||||||
|
final A attachment;
|
||||||
|
|
||||||
|
NotifierState(final State<T> next, final Notifier<? super T, A> notifier, final A attachment) {
|
||||||
|
- this.next = next;
|
||||||
|
+ super(next);
|
||||||
|
this.notifier = notifier;
|
||||||
|
this.attachment = attachment;
|
||||||
|
}
|
||||||
|
@@ -244,40 +378,41 @@ Status getStatus() {
|
||||||
|
return Status.WAITING;
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
doNotify(future);
|
||||||
|
- next.notifyDone(future, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
doNotify(future);
|
||||||
|
- next.notifyFailed(future, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
doNotify(future);
|
||||||
|
- next.notifyCancelled(future);
|
||||||
|
}
|
||||||
|
|
||||||
|
- void cancel() {
|
||||||
|
- next.cancel();
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ protected void doCancel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doNotify(final AbstractIoFuture<T> future) {
|
||||||
|
future.runNotifier(new NotifierRunnable<T, A>(notifier, future, attachment));
|
||||||
|
}
|
||||||
|
|
||||||
|
- boolean cancelRequested() {
|
||||||
|
- return next.cancelRequested();
|
||||||
|
+ @Override
|
||||||
|
+ protected boolean isCancelRequested() {
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- static final class WaiterState<T> extends State<T> {
|
||||||
|
- final State<T> next;
|
||||||
|
+ static final class WaiterState<T> extends NestedState<T> {
|
||||||
|
final Thread waiter;
|
||||||
|
|
||||||
|
WaiterState(final State<T> next, final Thread waiter) {
|
||||||
|
- this.next = next;
|
||||||
|
+ super(next);
|
||||||
|
this.waiter = waiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -285,36 +420,35 @@ Status getStatus() {
|
||||||
|
return Status.WAITING;
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
LockSupport.unpark(waiter);
|
||||||
|
- next.notifyDone(future, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
LockSupport.unpark(waiter);
|
||||||
|
- next.notifyFailed(future, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
LockSupport.unpark(waiter);
|
||||||
|
- next.notifyCancelled(future);
|
||||||
|
}
|
||||||
|
|
||||||
|
- void cancel() {
|
||||||
|
- next.cancel();
|
||||||
|
- }
|
||||||
|
+ @Override
|
||||||
|
+ protected void doCancel() {}
|
||||||
|
|
||||||
|
- boolean cancelRequested() {
|
||||||
|
- return next.cancelRequested();
|
||||||
|
+ @Override
|
||||||
|
+ protected boolean isCancelRequested() {
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- static final class CancellableState<T> extends State<T> {
|
||||||
|
- final State<T> next;
|
||||||
|
+ static final class CancellableState<T> extends NestedState<T> {
|
||||||
|
final Cancellable cancellable;
|
||||||
|
|
||||||
|
CancellableState(final State<T> next, final Cancellable cancellable) {
|
||||||
|
- this.next = next;
|
||||||
|
+ super(next);
|
||||||
|
this.cancellable = cancellable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -322,58 +456,60 @@ Status getStatus() {
|
||||||
|
return Status.WAITING;
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
- next.notifyDone(future, result);
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
- next.notifyFailed(future, exception);
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
- next.notifyCancelled(future);
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- void cancel() {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doCancel() {
|
||||||
|
try {
|
||||||
|
cancellable.cancel();
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
- next.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
- boolean cancelRequested() {
|
||||||
|
- return next.cancelRequested();
|
||||||
|
+ @Override
|
||||||
|
+ protected boolean isCancelRequested() {
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- static final class CancelRequestedState<T> extends State<T> {
|
||||||
|
- final State<T> next;
|
||||||
|
+ static final class CancelRequestedState<T> extends NestedState<T> {
|
||||||
|
|
||||||
|
CancelRequestedState(final State<T> next) {
|
||||||
|
- this.next = next;
|
||||||
|
+ super(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status getStatus() {
|
||||||
|
return Status.WAITING;
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
- next.notifyDone(future, result);
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyDone(final AbstractIoFuture<T> future, final T result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
- next.notifyFailed(future, exception);
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyFailed(final AbstractIoFuture<T> future, final IOException exception) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- void notifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
- next.notifyCancelled(future);
|
||||||
|
+ @Override
|
||||||
|
+ protected void doNotifyCancelled(final AbstractIoFuture<T> future) {
|
||||||
|
}
|
||||||
|
|
||||||
|
- void cancel() {
|
||||||
|
+ @Override
|
||||||
|
+ protected void doCancel() {
|
||||||
|
// terminate
|
||||||
|
}
|
||||||
|
|
||||||
|
- boolean cancelRequested() {
|
||||||
|
+ @Override
|
||||||
|
+ protected boolean isCancelRequested() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Name: xnio
|
Name: xnio
|
||||||
Version: 3.4.0
|
Version: 3.4.0
|
||||||
Release: 10
|
Release: 11
|
||||||
Summary: A simplified low-level I/O layer
|
Summary: A simplified low-level I/O layer
|
||||||
License: ASL 2.0 and LGPLv2+
|
License: ASL 2.0 and LGPLv2+
|
||||||
URL: http://www.jboss.org/xnio
|
URL: http://www.jboss.org/xnio
|
||||||
@ -18,6 +18,9 @@ BuildRequires: mvn(org.wildfly.common:wildfly-common)
|
|||||||
Patch0001: 0001-Disable-tests-use-TLSv1-protocol.patch
|
Patch0001: 0001-Disable-tests-use-TLSv1-protocol.patch
|
||||||
Patch0002: 0002-skip-connect-timeout.patch
|
Patch0002: 0002-skip-connect-timeout.patch
|
||||||
Patch0003: 0003-skip-Future-cancel-test-case.patch
|
Patch0003: 0003-skip-Future-cancel-test-case.patch
|
||||||
|
|
||||||
|
Patch3000: backport-CVE-2023-5685.patch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
XNIO is a simplified low-level I/O layer which can be used anywhere you are using NIO today.
|
XNIO is a simplified low-level I/O layer which can be used anywhere you are using NIO today.
|
||||||
It frees you from the hassle of dealing with Selectors and the lack of NIO support for
|
It frees you from the hassle of dealing with Selectors and the lack of NIO support for
|
||||||
@ -67,6 +70,9 @@ rm api/src/test/java/org/xnio/racecondition/ResumeReadsOnHandlingReadableChannel
|
|||||||
%files help -f .mfiles-javadoc
|
%files help -f .mfiles-javadoc
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Nov 06 2024 yaoxin <yao_xin001@hoperun.com> - 3.4.0-11
|
||||||
|
- Fix CVE-2023-5685
|
||||||
|
|
||||||
* Tue Aug 23 2022 liyanan <liyanan32@h-partners.com> - 3.4.0-10
|
* Tue Aug 23 2022 liyanan <liyanan32@h-partners.com> - 3.4.0-10
|
||||||
- skip cancelAcceptStreamConnection test case
|
- skip cancelAcceptStreamConnection test case
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user