Skip to content

Fix bind local device#929

Merged
bradh352 merged 1 commit into
c-ares:mainfrom
marcovsz:marcovsz-patch-1
Dec 12, 2024
Merged

Fix bind local device#929
bradh352 merged 1 commit into
c-ares:mainfrom
marcovsz:marcovsz-patch-1

Conversation

@marcovsz
Copy link
Copy Markdown
Contributor

sizeof(channel->local_dev_name) will always be 32 and cause ares_str_isprint() check failed in default_asetsockopt()

@createyourpersonalaccount
Copy link
Copy Markdown
Contributor

New code does not store the NUL byte. What bug is this fixing? If you invoke default_asetsockopt with the right number, namely the string length, it will not fail as you claim.

@marcovsz
Copy link
Copy Markdown
Contributor Author

marcovsz commented Dec 6, 2024

If we set channel->local_dev_name to "eth0", sizeof(channel->local_dev_name) is 32, ares_strlen(channel->local_dev_name) is 4, the function calling of default_asetsockopt(sock, ARES_SOCKET_OPT_BIND_DEVICE, "ccmni0", 32, user_data) is not working as expected. It returns -1 after ares_str_isprint() check failed, doesn't run to setsockopt line.

case ARES_SOCKET_OPT_BIND_DEVICE:
if (!ares_str_isprint(val, (size_t)val_size)) {
SET_SOCKERRNO(EINVAL);
return -1;
}
#ifdef SO_BINDTODEVICE
return setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, val, val_size);
#else
SET_SOCKERRNO(ENOSYS);
return -1;
#endif

@bradh352
Copy link
Copy Markdown
Member

bradh352 commented Dec 6, 2024

manpage does say it needs to be a null-terminated string. That said, it doesn't say if the length provided needs to include the NUL character.

That said, the logic here is definitely wrong:

if (!ares_str_isprint(val, (size_t)val_size)) {

We should check that the buffer up to the first NUL byte (not to exceed the provided length) is printable.
We probably need an ares_strlen_max() helper (aka strnlen()) to do this.

I think the change in this PR is also valid, however, especially if its been tested to work. But the function called should also be fixed to prevent regressions in the future.

@createyourpersonalaccount
Copy link
Copy Markdown
Contributor

The old code writes exact amount (32) of bytes. The new code uses strlen without bounds-checking, writing an arbitrary amount of bytes to fixed-width array. There is also an issue of a buffer overflow.

@bradh352
Copy link
Copy Markdown
Member

bradh352 commented Dec 6, 2024

channel->local_dev_name is a buffer we provide during and copied into during ares_init_options, so its guaranteed to be a valid null-terminated string without overflow.

createyourpersonalaccount added a commit to createyourpersonalaccount/c-ares that referenced this pull request Dec 7, 2024
Add a new function `ares_strnlen()` to fix the logic in
default_asetsockopt(), see
<c-ares#929 (comment)>.
bradh352 pushed a commit that referenced this pull request Dec 11, 2024
Add a new function `ares_strnlen()` to fix the logic in
default_asetsockopt(), see
<#929 (comment)>.

Authored-By: Nikolaos Chatzikonstantinou (@createyourpersonalaccount)
bradh352 pushed a commit that referenced this pull request Dec 11, 2024
Add a new function `ares_strnlen()` to fix the logic in
default_asetsockopt(), see
<#929 (comment)>.

Authored-By: Nikolaos Chatzikonstantinou (@createyourpersonalaccount)
@marcovsz
Copy link
Copy Markdown
Contributor Author

manpage does say it needs to be a null-terminated string. That said, it doesn't say if the length provided needs to include the NUL character.

That said, the logic here is definitely wrong:

if (!ares_str_isprint(val, (size_t)val_size)) {

We should check that the buffer up to the first NUL byte (not to exceed the provided length) is printable. We probably need an ares_strlen_max() helper (aka strnlen()) to do this.

I think the change in this PR is also valid, however, especially if its been tested to work. But the function called should also be fixed to prevent regressions in the future.

Of course this change works for me(on an Android Arm platform)

@bradh352 bradh352 merged commit 608507d into c-ares:main Dec 12, 2024
bradh352 added a commit that referenced this pull request Dec 12, 2024
…ator (#935)

See #929 for discussion

Signed-off-by: Brad House (@bradh352)
bradh352 pushed a commit that referenced this pull request Dec 12, 2024
sizeof(channel->local_dev_name) will always be 32 and cause
ares_str_isprint() check failed in default_asetsockopt()

Fix By: @marcovsz
bradh352 added a commit that referenced this pull request Dec 12, 2024
…ator (#935)

See #929 for discussion

Signed-off-by: Brad House (@bradh352)
michael-dev pushed a commit to HamelinPorts/android_external_c-ares that referenced this pull request Apr 25, 2026
Add a new function `ares_strnlen()` to fix the logic in
default_asetsockopt(), see
<c-ares#929 (comment)>.

Authored-By: Nikolaos Chatzikonstantinou (@createyourpersonalaccount)
michael-dev pushed a commit to HamelinPorts/android_external_c-ares that referenced this pull request Apr 25, 2026
sizeof(channel->local_dev_name) will always be 32 and cause
ares_str_isprint() check failed in default_asetsockopt()

Fix By: @marcovsz
michael-dev pushed a commit to HamelinPorts/android_external_c-ares that referenced this pull request Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants