-
Notifications
You must be signed in to change notification settings - Fork 6
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
Fix #39: getaddrinfo numeric error codes are now translated #40
Conversation
The (relatively) new Suite 20 second timeout has already saved me |
The context for this change is that as I probe IPv6 support, I cause lots of gaiaddrinfo errors, sometimes |
A CI that does not take 2 hours to run (and then fail). What a joy! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Happy to see error messages being improved.
Do you think we can simulate some of these errors in our test suite? If so, then what would you think about aiming to make our error messages consistent with those used by the JVM/JDK?
|
||
val port = addr.getPort.toString | ||
|
||
s"${gaiMsg} address: ${adr} port: ${port}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are your thoughts on the security concersn with including the address
and port
in the error message? We recently had this exact discussion on the Typelevel Discord.
Some insights from Michael Pilquist:
any security concerns about including host/port in the error message? e.g., imagine an http4s route that tries to make a request to some other service and fails with timeout -- that exception message would get propagated to client, exposing internal hosts/port info
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the review & raising the concern.
TL;DR
If there is any chance that the info will impede upstream adoption, I will remove
it and use a private version. No problem.
Longer discussion:
Personal opinion:
Bad actors are incredibly clever at exploiting any lack of entropy. Witness all the
Intel & AMD speculative execution hacks.
People trying to fix problems depend upon there being a lack of entropy: i.e. information.
The very fact that a getaddrinfo message of any kind is being reported gives
suitably motivated bad actors information. Removing even a simple message
makes life difficult/impossible for the "fixers".
"fixers" can be overwhelmed by too much information, so finding the appropriate
amount is a changing goal.
Here the port number probably gives away the most information.
The address is in n.n.n.n or (soon) xxxx::x notation, not a string
"secrets.com". The numeric address can be translated, but
it takes someone's time and a bit of skill.
The understanding of "Industry best-practice" changes over time.
At this point and for the foreseeable future I think giving at
least the basic getaddrinfo code translation can be defended
as "Industry standard".
I think we concur that Rapid prototyping
is not an occasion for a security give-away.
Security analysis is essential but needs to be considered in scope: valid security, extra-cautious security,
paranoid security, and security-theater.
I think the base PR is safe but not worth investing the time to defend to the
"deny any information at all" folks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sharing your thoughts. Unfortunately I am not a security expert, so in doubt I defer to the JVM: can we simulate some of these errors in our test suite, and make the exceptions match what the JVM does in the same situation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like Java 17 ServerSocket bind
distinguishes EAI_FAMILY (unsupported address family)
and throws an IllegalArgumentException
. In other cases it throws IOException
. The
current epoll code always throws IOException
(with a message that would give the unsupported
AF, but probably not tell which af it got). That is fixable.
I can try to provoke the a SocketServer bind IOException and see exactly what
text it returns. Will take time (day or two-ish).
Then I have to check the java.nio Channel area to see if there is any
complication/change in message.
I can submit the simple (no address, no port) gai_message updates
so they do not get lost on my end. Understanding that they are on
hold whilst I find out what Java does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for understanding! That sounds like a good plan to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update:
Java 17 AsynchronousSeverSocketChannel throws UnsupportedAddressTypeException
not IllegalArgumentException
for wrong AF. I expect AsynchronousSocketChannel to to the same but will check before implementing.
Arman, Per our helpful discussion,:
This particular path should never be seen, but if it is, they now match JVM describes no
I had to fudge things a bit for 0.4.5 (?) because EADDRNOTAVAIL is not available there.
This is a second evolution, there are probably 99 or more evolutions to go, but PS: During the course of this work, I discovered that |
Thanks, Lee, that's looking great! For every new exception that you add, would you mind adding a test as well? I already have a few existing tests to verify that exceptions match. epollcat/tests/shared/src/test/scala/epollcat/TcpSuite.scala Lines 232 to 261 in a4544f0
|
Agreed, a good concept. When you say "new" do you mean new as in adding new "FooException.scala" java.nio.channels.UnsupportedAddressTypeExceptionIn this particular case, I had that concern in mind, as it I could not figure out a way to cause the Exception at runtime. EADDRNOTAVAILI will add a runtime test for this. I have a number of cases which |
Yes, every new use. Essentially every time we add a new conditional branch to our sources.
Yeah, no problem. If we can find a way it's always good to add a test to lock in the behavior, if it's non-trivial then let's just move on. Thanks! |
4bc03c3
to
5fadc54
Compare
I added a test for BindException EADDRNOTAVAIL. It can probably be minimized and/or The current test focuses on the failing call bind. The models I had to work from |
|
And, of course, macOS has a slightly different message "'Can't assign requested address" (macOS). A learning opportunity for me to figure out how to get |
Ha, annoying! Instead of writing a regex why not use an if-else switch with the OS check? |
I am studying munit-cats-effect in another window. Looks like I am off to look for models. |
_ <- ch.bind(new InetSocketAddress("240.0.0.1", 0)) | ||
} yield () | ||
} | ||
.interceptMessage[BindException]("Cannot assign requested address") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LeeTibbert why not do this?
.interceptMessage[BindException]("Cannot assign requested address") | |
.interceptMessage[BindException]( | |
if (isLinux) "Cannot assign requested address" | |
else "Can't assign requested address" | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the suggestion. I did not know that was possible. Learning new things is good,
but also an exercise in humility.
The code snippet works fine on SN, after importing LinktimeInfo.
Understandably, it fails on JVM. May need to factor this test out and
use the fact that epollcat is a multi-project to have a new Suite
of OS specific tests. I hate having duplicate code, as it
is hard to keep in sync. So, worst case, I/we can fix this.
I am off to look around to see how the test might determine
the OS it is running on. (perhaps more complicate code
within the intercept message to read the System Property
"os.name") Can the code (thunk?) have more than one
statement, as long as it returns a String?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can add this definition at the top of the suite:
val isLinux = {
val osName = Option(System.getProperty("os.name"))
osName.exists(_.toLowerCase().contains("linux"))
}
I have the runtime "os.name" test working JVM & SN on Linux. Off to As events unfold, we will probably want to move this test to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well that was quite an adventure! Thanks for chasing those down 😃
Is this ready for final review? Because it is LGTM. Merge at will :)
Thank you for the review and tutorage. I may end up learning some Cats IO. I think this is ready for merge at your convenience. |
I'd say you've got the hang of it, you did a very nice job with the test :) |
Numeric error codes returned from
getaddrinfo
are now translated to text.Fixes #39.
Previously:
After this PR:
Most developers will never see these messages, but those who do will
appreciate the time savings.