Skip to content

Add getaddrinfo and freeaddrinfo shims#4984

Open
WhySoBad wants to merge 7 commits intorust-lang:masterfrom
WhySoBad:network-socket-dns
Open

Add getaddrinfo and freeaddrinfo shims#4984
WhySoBad wants to merge 7 commits intorust-lang:masterfrom
WhySoBad:network-socket-dns

Conversation

@WhySoBad
Copy link
Copy Markdown
Contributor

Hi,

This pull request adds shims for the getaddrinfo and freeaddrinfo syscalls. They are used by the ToSocketAddrs trait in the standard library to resolve hostnames to socket addresses.
Because the abstraction of the standard library is very tight, we're pretty much only able to shim the exact use case of the standard library.

Also, we cannot shim gai_strerror because the standard library doesn't have ErrorKinds for the DNS errors. This is a bit unfortunate because Miri will throw an unsupported error when there is a resolution error (e.g. hostname doesn't exist).

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 28, 2026

Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two.
Please remember to not force-push to the PR branch except when you need to rebase due to a conflict or when the reviewer asks you for it.

@rustbot rustbot added the S-waiting-on-review Status: Waiting for a review to complete label Apr 28, 2026
@RalfJung
Copy link
Copy Markdown
Member

Also, we cannot shim gai_strerror because the standard library doesn't have ErrorKinds for the DNS errors. This is a bit unfortunate because Miri will throw an unsupported error when there is a resolution error (e.g. hostname doesn't exist).

Can't we at least return something generic, like what our strerror_r shim does when encountering an unknown error kind?

@WhySoBad
Copy link
Copy Markdown
Contributor Author

Yeah we can do that.

@WhySoBad
Copy link
Copy Markdown
Contributor Author

WhySoBad commented Apr 28, 2026

Unlike strerror_r, gai_strerror doesn't take a buffer argument so we need to do static allocations for the error messages. Since we have the AddressInfoStore anyways, I was thinking about adding the error allocations there.

And we also have the problem that io_error_to_errnum throws an unsupported error here:

miri/src/shims/io_error.rs

Lines 249 to 260 in 3f8007e

/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
/// as a platform-specific errnum.
fn io_error_to_errnum(&self, err: std::io::Error) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_ref();
let target = &this.tcx.sess.target;
if target.families.iter().any(|f| f == "unix") {
for &(name, kind) in UNIX_IO_ERROR_TABLE {
if err.kind() == kind {
return interp_ok(this.eval_libc(name));
}
}
throw_unsup_format!("unsupported io error: {err}")

Are there any other shims which needed to circumvent this method?

@RalfJung
Copy link
Copy Markdown
Member

And we also have the problem that io_error_to_errnum throws an unsupported error here:

What are the errnums you are getting?

@WhySoBad
Copy link
Copy Markdown
Contributor Author

Well, we only get a an Uncategorized io::ErrorKind because the io::Error is constructed manually here: https://github.com/rust-lang/rust/blob/HEAD/library/std/src/sys/net/connection/socket/unix.rs#L53

The problem is that the UNIX_IO_ERROR_TABLE doesn't contain an entry for Uncategorized (which it isn't exposed to because we shouldn't match against that).

@RalfJung
Copy link
Copy Markdown
Member

RalfJung commented Apr 29, 2026

Ah so the actual problem is that

  • getaddrinfo returns an error code (but not a standard errnum code, these are specific DNS error codes)
  • std translates that into a string
  • we now have to somehow get a code back out of that again

There's no standard Unix errnum involved here ever, std just shoves this into an io::Error because it has to.

Comment thread src/shims/unix/socket.rs Outdated

let socket_addrs = match (node_str, port).to_socket_addrs() {
Ok(addrs) => addrs,
Err(e) => return this.set_last_error_and_return_i32(e),
Copy link
Copy Markdown
Member

@RalfJung RalfJung Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this set_last_error_and_return_i32 call here doesn't really make sense. It means we return -1 on error but that's not how getaddrinfo works.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see, it shouldn't set errno but instead just return the negative integer instead. I've misread the man page. But the problem with unmapped error codes remains for #4987.

Copy link
Copy Markdown
Member

@RalfJung RalfJung Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, and also here we have the problem of even figuring out what to return. std hides the actual error code from us. We can just guess something but it's not great.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's a problem. So should I just return something like EAI_FAIL because it's kind of a permanent failure?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking EAI_SYSTEM and then set errno to the closest approximation of "we have no idea". Maybe EPROTO?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable. Maybe we should also emit a warning every time we return a bogus error such that it's clear that this wasn't the real error?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we only emit warnings the first time this happens, but that seems reasonable yeah.

@WhySoBad
Copy link
Copy Markdown
Contributor Author

No, we get standard UNIX error codes back -- they are just DNS specific:

RETURN VALUE
     getaddrinfo() returns 0 if it succeeds, or one of the following nonzero error codes:

     EAI_ADDRFAMILY
            The specified network host does not have any network addresses in the requested address family.

     EAI_AGAIN
            The name server returned a temporary failure indication.  Try again later.

     EAI_BADFLAGS
            hints.ai_flags contains invalid flags; or, hints.ai_flags included AI_CANONNAME and node was NULL.

     EAI_FAIL
            The name server returned a permanent failure indication.

     EAI_FAMILY
            The requested address family is not supported.

     EAI_MEMORY
            Out of memory.

     EAI_NODATA
            The specified network host exists, but does not have any network addresses defined.

     EAI_NONAME
            The node or service is not known; or both node and service are NULL; or AI_NUMERICSERV was specified in hints.ai_flags and
            service was not a numeric port-number string.

     EAI_SERVICE
            The requested service is not available for the requested socket type.  It may be available through  another  socket  type.
            For  example,  this  error  could  occur  if  service was "shell" (a service available only on stream sockets), and either
            hints.ai_protocol was IPPROTO_UDP, or hints.ai_socktype was SOCK_DGRAM; or the error could occur if service was not  NULL,
            and hints.ai_socktype was SOCK_RAW (a socket type that does not support the concept of services).

     EAI_SOCKTYPE
            The requested socket type is not supported.  This could occur, for example, if hints.ai_socktype and hints.ai_protocol are
            inconsistent (e.g., SOCK_DGRAM and IPPROTO_TCP, respectively).

     EAI_SYSTEM
            Other system error; errno is set to indicate the error.

     The gai_strerror() function translates these error codes to a human readable string, suitable for error reporting.

And the standard library has by far not all UNIX error codes mapped to io::ErrorKinds (there are some experimental features to add more variants, but even with those features the DNS errorcodes aren't covered).
For unmapped io::ErrorKinds there is just the io::ErrorKind::Uncategorized which shouldn't be matched against because error kinds which map to might receive their own io::ErrorKind variant in the future.

@RalfJung
Copy link
Copy Markdown
Member

RalfJung commented Apr 29, 2026

No, we get standard UNIX error codes back

These are not standard unix error codes. EAI_* are negative numbers directly returned from that function. Normal unix error codes are positive and they are stored in errnum and the function returns -1.

This is basically a separate error enum specifically for getaddrinfo.

@RalfJung
Copy link
Copy Markdown
Member

For unmapped io::ErrorKinds there is just the io::ErrorKind::Uncategorized which shouldn't be matched against because error kinds which map to might receive their own io::ErrorKind variant in the future.

No, io::Error can represent all host errors, even "unmapped" ones. That's what Error::from_raw_os_error is for.

But that's only for "normal" host error codes, not for this other kind of error code that getaddrinfo returns.

@rustbot

This comment has been minimized.

@WhySoBad WhySoBad force-pushed the network-socket-dns branch from ad84f51 to 378d89c Compare May 1, 2026 18:52
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 1, 2026

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Waiting for a review to complete

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants