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

Crash in AddressToJS for udp6 socket bound to link-local address #41500

Closed
darkk opened this issue Jan 13, 2022 · 0 comments · Fixed by #41547
Closed

Crash in AddressToJS for udp6 socket bound to link-local address #41500

darkk opened this issue Jan 13, 2022 · 0 comments · Fixed by #41547
Labels
dgram Issues and PRs related to the dgram subsystem / UDP.

Comments

@darkk
Copy link

darkk commented Jan 13, 2022

Version

v17.3.1

Platform

Linux darkk-ya-laptop 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

dgram

What steps will reproduce the bug?

Use the following four files to build the test-case:

  • dgram-udp6-address.js:
'use strict';

const dgram = require('dgram');
const socket = dgram.createSocket({ type: 'udp6' });

const discard_port = 9;
const global_ipv6 = '2600::';

// It might be rejected if there is no route to the ip (e.g. IPv4-only network).
socket.connect(discard_port, global_ipv6, err => {
  if (err === undefined) {
    console.log('remoteAddress: ', socket.remoteAddress());
    // The next line triggers assertion under certain conditions:
    // node[631]: ../src/tcp_wrap.cc:354:v8::Local<v8::Object> node::AddressToJS(node::Environment*, const sockaddr*, v8::Local<v8::Object>): Assertion `(r) == (0)' failed.
    console.log('address: ', socket.address());
  } else {
    console.log('UDP connection error', err);
  }
  socket.unref();
});
  • Dockerfile:
FROM node:17-bullseye

RUN set -ex \
    && apt-get update \
    && apt-get install -y --no-install-recommends iproute2 \
    && :

COPY --chown=0:0 \
    dgram-udp6-address.js \
    test.sh \
    /
  • test.sh:
#!/bin/bash

set -ex

ip link add dummy0 type dummy
ip link set dummy0 up
ip -6 address add fe80::aaaa:bbbb:cccc:dddd dev dummy0
ip -6 route add default dev dummy0
ip addr
ip -6 route
node --version
node /dgram-udp6-address.js
  • run.sh:
#!/bin/bash

set -ex

tar cz Dockerfile dgram-udp6-address.js test.sh | docker build -t dgram-udp6-address:latest -

exec docker run --rm --tty -i \
    --privileged \
    --net=none \
     --sysctl net.ipv6.conf.all.disable_ipv6=0 \
    dgram-udp6-address:latest \
    /bin/bash /test.sh

The test-case is run with ./run.sh.

How often does it reproduce? Is there a required condition?

It's 100% reproducible with this network set-up.

This network setup simulates the default setup of Rostelecom ISP in St. Petersburg regarding their handling of IPv6 as seen by my Ubuntu 16.04 laptop:

  • the ISP-provided router announces a default gateway via link-local address fe80::1
  • local machines get link-local address
  • no real IPv6 connectivity is provided
  • the router responds with ICMP6, destination unreachable, unreachable route to IPv6 packets with global destination

What is the expected behavior?

node should not crash whole app. It should rather be some kind of exception, socket error or something like that.

I've noticed the behavior while developing Electron app, whole app was terminated on socket.address() call.

What do you see instead?

...
+ node /dgram-udp6-address.js
remoteAddress:  { address: '2600::', family: 'IPv6', port: 9 }
node[15]: ../src/tcp_wrap.cc:372:v8::Local<v8::Object> node::AddressToJS(node::Environment*, const sockaddr*, v8::Local<v8::Object>): Assertion `(r) == (0)' failed.
 1: 0xb2c330 node::Abort() [node]
 2: 0xb2c3ae  [node]
 3: 0xc1da97 node::AddressToJS(node::Environment*, sockaddr const*, v8::Local<v8::Object>) [node]
 4: 0xc2f2ad void node::GetSockOrPeerName<node::UDPWrap, &uv_udp_getsockname>(v8::FunctionCallbackInfo<v8::Value> const&) [node]
 5: 0xd798de  [node]
 6: 0xd7acff v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
 7: 0x162fff9  [node]
/test.sh: line 12:    15 Aborted                 (core dumped) node /dgram-udp6-address.js

Additional information

Other affected versions are v12.22.8, v14.18.2, v16.13.1

Relevant strace snippet is:

socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 17
bind(17, {sa_family=AF_INET6, sin6_port=htons(0), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::", &sin6_addr), sin6_scope_id=0}, 28) = 0
connect(17, {sa_family=AF_INET6, sin6_port=htons(9), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "2600::", &sin6_addr), sin6_scope_id=0}, 28) = 0
getpeername(17, {sa_family=AF_INET6, sin6_port=htons(9), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "2600::", &sin6_addr), sin6_scope_id=0}, [128->28]) = 0

remoteAddress:  { address: '2600::', family: 'IPv6', port: 9 }

getsockname(17, {sa_family=AF_INET6, sin6_port=htons(44890), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "fe80::aaaa:bbbb:cccc:dddd", &sin6_addr), sin6_scope_id=0}, [128->28]) = 0
access("/proc/net", R_OK)               = 0
access("/proc/net/unix", R_OK)          = 0
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 20
ioctl(20, SIOCGIFNAME, {ifr_index=0})   = -1 ENODEV (No such device)
close(20)                               = 0
getpid()                                = 18

node[18]: ../src/tcp_wrap.cc:372:v8::Local<v8::Object> node::AddressToJS(node::Environment*, const sockaddr*, v8::Local<v8::Object>): Assertion `(r) == (0)' failed.

So, the kernel returns sin6_flowinfo=htonl(0) for the bound socket, so the assertion is false.

#39143 seems to be a similar issue on AIX.

@Mesteery Mesteery added the dgram Issues and PRs related to the dgram subsystem / UDP. label Jan 13, 2022
santigimeno added a commit to santigimeno/node that referenced this issue Jan 15, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: nodejs#41500
santigimeno added a commit to santigimeno/node that referenced this issue Feb 2, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: nodejs#41500
santigimeno added a commit to santigimeno/node that referenced this issue Feb 2, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: nodejs#41500
nodejs-github-bot pushed a commit that referenced this issue Feb 11, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: #41500

PR-URL: #41547
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
bengl pushed a commit to bengl/node that referenced this issue Feb 21, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: nodejs#41500

PR-URL: nodejs#41547
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
bengl pushed a commit to bengl/node that referenced this issue Feb 21, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: nodejs#41500

PR-URL: nodejs#41547
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
danielleadams pushed a commit to danielleadams/node that referenced this issue Apr 21, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: nodejs#41500

PR-URL: nodejs#41547
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
danielleadams pushed a commit that referenced this issue Apr 24, 2022
An interface with index 0 doesn't make sense and makes
`if_indextoname()` to return `ENXIO` which crashes the process.

Fixes: #41500

PR-URL: #41547
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dgram Issues and PRs related to the dgram subsystem / UDP.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants