Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UnsupportedOperationException after Netty 4.1.60 update #7953

Closed
Scottmitch opened this issue Mar 9, 2021 · 6 comments · Fixed by pravega/pravega#6393
Closed

UnsupportedOperationException after Netty 4.1.60 update #7953

Scottmitch opened this issue Mar 9, 2021 · 6 comments · Fixed by pravega/pravega#6393
Assignees
Milestone

Comments

@Scottmitch
Copy link

Scottmitch commented Mar 9, 2021

What version of gRPC-Java are you using?

1.36.0

What is your environment?

macOS, jdk11

What did you expect to see?

Server can process a request which contains content-length header.

What did you see instead?

A change in Netty 4.1.60 introduces usage of the Http2Headers#setLong(..) method, but grpc-java's custom header implementations do not implement this method (e.g. throw UnsupportedOperationException).

java.lang.UnsupportedOperationException
	at io.grpc.netty.AbstractHttp2Headers.setLong(AbstractHttp2Headers.java:465)
	at io.grpc.netty.AbstractHttp2Headers.setLong(AbstractHttp2Headers.java:26)
	at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder$FrameReadListener.onHeadersRead(DefaultHttp2ConnectionDecoder.java:403)
	at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder$FrameReadListener.onHeadersRead(DefaultHttp2ConnectionDecoder.java:347)
	at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder$PrefaceFrameListener.onHeadersRead(DefaultHttp2ConnectionDecoder.java:707)
	at io.netty.handler.codec.http2.Http2InboundFrameLogger$1.onHeadersRead(Http2InboundFrameLogger.java:56)
	at io.netty.handler.codec.http2.DefaultHttp2FrameReader$2.processFragment(DefaultHttp2FrameReader.java:483)
	at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readHeadersFrame(DefaultHttp2FrameReader.java:491)
	at io.netty.handler.codec.http2.DefaultHttp2FrameReader.processPayloadState(DefaultHttp2FrameReader.java:254)
	at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readFrame(DefaultHttp2FrameReader.java:160)
	at io.netty.handler.codec.http2.Http2InboundFrameLogger.readFrame(Http2InboundFrameLogger.java:41)
	at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder.decodeFrame(DefaultHttp2ConnectionDecoder.java:181)
	at io.netty.handler.codec.http2.Http2ConnectionHandler$FrameDecoder.decode(Http2ConnectionHandler.java:378)
	at io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:242)
	at io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:438)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)

Steps to reproduce the bug

  1. upgrade netty dependency to 4.1.60.Final
  2. send a request with content-length header
  3. server should fail to process the request with the exception above.
@Scottmitch Scottmitch changed the title Nett UnsupportedOperationException after Netty 4.1.60 update Mar 9, 2021
@sanjaypujare
Copy link
Contributor

sanjaypujare commented Mar 10, 2021

@ejona86 we discussed this today and IIRC we have a plan to fix this ASAP, right?

@Scottmitch you have the workaround of not upgrading the netty dependency to 4.1.60.Final and leave it to what grpc has (4.1.52.Final ?)

@ejona86
Copy link
Member

ejona86 commented Mar 10, 2021

Yeah, most users are using grpc-netty-shaded and so won't have this trouble. But we do want to help those using grpc-netty to allow them to upgrade Netty. We should implement the missing method and backport it to a 1.36.1 and 1.35.1.

Scottmitch added a commit to Scottmitch/servicetalk-1 that referenced this issue Mar 10, 2021
Modifications:
- Add workaround to ProtocolCompatibilityTest for
grpc/grpc-java#7953.
- Remove ServiceTalk content-length validation which is now implemented
  by Netty.
Scottmitch added a commit to Scottmitch/servicetalk-1 that referenced this issue Mar 10, 2021
Modifications:
- Add workaround to ProtocolCompatibilityTest for
grpc/grpc-java#7953.
Scottmitch added a commit to apple/servicetalk that referenced this issue Mar 10, 2021
Modifications:
- Add workaround to ProtocolCompatibilityTest for
grpc/grpc-java#7953.
ejona86 added a commit to ejona86/grpc-java that referenced this issue Mar 12, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
grpc#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
ejona86 added a commit to ejona86/grpc-java that referenced this issue Mar 12, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
grpc#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
ejona86 added a commit to ejona86/grpc-java that referenced this issue Mar 12, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
grpc#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
@ejona86 ejona86 self-assigned this Mar 12, 2021
@ejona86 ejona86 added this to the 1.37 milestone Mar 12, 2021
ejona86 added a commit that referenced this issue Mar 16, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
ejona86 added a commit to ejona86/grpc-java that referenced this issue Mar 18, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
grpc#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
ejona86 added a commit to ejona86/grpc-java that referenced this issue Mar 18, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
grpc#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
ejona86 added a commit that referenced this issue Mar 18, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
ejona86 added a commit that referenced this issue Mar 18, 2021
Starting in Netty 4.1.60, Netty will validate Content-Length headers
using getAll() and setLong(). While getAll() was documented as only used
in tests, it doesn't appear it was currently used in any tests.

While Http2NettyTest.contentLengthPermitted() was added to confirm that
Content-Length works, it won't actually exercise any interesting
behavior until we upgrade to Netty 4.1.60. However, I did test with
Netty 4.1.60 and it reproduced the failure in
#7953 and passed with this
change.

Since Netty is now observing/modifying the headers, it would seem
appropriate to implement a substantial portion of the Http2Headers API.
However, the surface is much larger than we'd want to implement for a
'quick fix' that could be backported. In addition, it seems much of the
API is just convenience methods, so it is probably appropriate to split
out a AbstractHeaders class from DefaultHeaders in Netty that doesn't
make any assumptions about the header storage mechanism.
@xenji
Copy link

xenji commented Mar 22, 2021

There is a critical CVE for netty 4.1.52. Is there any plan to upgrade the shaded version?

grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-buffer/pom.xml (pkg:maven/io.netty/netty-buffer@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-codec-http/pom.xml (pkg:maven/io.netty/netty-codec-http@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-codec-http2/pom.xml (pkg:maven/io.netty/netty-codec-http2@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-codec-socks/pom.xml (pkg:maven/io.netty/netty-codec-socks@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-codec/pom.xml (pkg:maven/io.netty/netty-codec@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-common/pom.xml (pkg:maven/io.netty/netty-common@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-handler-proxy/pom.xml (pkg:maven/io.netty/netty-handler-proxy@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-handler/pom.xml (pkg:maven/io.netty/netty-handler@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-resolver/pom.xml (pkg:maven/io.netty/netty-resolver@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-transport-native-epoll/pom.xml (pkg:maven/io.netty/netty-transport-native-epoll@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-transport-native-unix-common/pom.xml (pkg:maven/io.netty/netty-transport-native-unix-common@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290
grpc-netty-shaded-1.36.0.jar/META-INF/maven/io.netty/netty-transport/pom.xml (pkg:maven/io.netty/netty-transport@4.1.52.Final, cpe:2.3:a:netty:netty:4.1.52:*:*:*:*:*:*:*) : CVE-2021-21290

@ejona86
Copy link
Member

ejona86 commented Mar 22, 2021

Is there any plan to upgrade the shaded version?

No, not for the CVEs as they do not impact gRPC. If you are using grpc-netty-shaded there is no issue.

Also, netty/netty-jni-util#5 prevents us from upgrading to recent releases. (But like I said before, we do want to be compatible with new releases for grpc-netty.)

@njhill
Copy link
Contributor

njhill commented Mar 23, 2021

Sorry to bug but is there an ETA for 1.36.x release with this fix in?

@ejona86
Copy link
Member

ejona86 commented Mar 24, 2021

Fixed by #7967. v1.35.1 and v1.36.1 are now released that include this backport. v1.36.1 beat v1.35.1 by a few hours, so don't be surprised if you don't see v1.35.1 yet.

Scottmitch added a commit to apple/servicetalk that referenced this issue Mar 25, 2021
Modifications:
- Remove workarounds in ProtocolCompatibilityTest for
grpc/grpc-java#7953
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 23, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants