termux / termux-packages

A package build system for Termux.
https://termux.dev
Other
13.12k stars 3.01k forks source link

[Bug]: Nodejs uv_interface_addresses returned Unknown system error 13 #10868

Open neophob opened 2 years ago

neophob commented 2 years ago

Problem description

When I use the Termux app, install Node.js (latest and lts) and run Node.js - the call to os.networkInterfaces() works.

However when I build Node.js myself using the Termux Docker images (./build-package.sh openssl nodejs), each call to os.networkInterfaces() fails with A system error occurred: uv_interface_addresses returned Unknown system error 13 (Unknown system error 13) on my Android 11 system. (Permission denied).

it looks like this is because Android 11 forbids apps to query MAC addresses. Links:

What steps will reproduce the bug?

start self compiled nodejs binary on your Android 11 phone, enter os.networkInterfaces() in the repl.

Tested with the latest nodejs and nodejs-lts version

What is the expected behavior?

call does not fail

System information

termux-info:

Grimler91 commented 2 years ago

Did you build in the docker image, or by git cloning termux-packages and running ./build-package.sh on device?

Building in the docker image should give an identical nodejs{-lts} package as the one in our repos, unless you've made changes to the build recipe?

neophob commented 2 years ago

I did git cloning termux-packages and running ./build-package.sh - but not on the device but on my macbook.

And no changes to the nodejs packages - i basically followed https://github.com/termux/termux-packages/wiki/Build-environment and https://github.com/termux/termux-packages/wiki/Building-packages

more background information: I want to run a nodejs app on Android and use https://github.com/siepra/node-on-android-demo as starting point.

neophob commented 2 years ago

Note: I did NOT build the node package on my Android device, but on my Macbook in a Docker container. I the installed the node binary on my Android device. So I think the "on-device packaging" tag is wrong.

neophob commented 2 years ago

More info:

thunder-coding commented 2 years ago

@neophob Can you try building Node.js with the following additional patch:-

--- ./deps/uv/src/unix/linux-core.c.orig    2022-06-03 12:37:01.127102137 +0530
+++ ./deps/uv/src/unix/linux-core.c 2022-06-03 12:37:11.887102132 +0530
@@ -43,14 +43,6 @@
 #include <fcntl.h>
 #include <time.h>

-#define HAVE_IFADDRS_H 1
-
-#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
-#  undef HAVE_IFADDRS_H
-# endif
-#endif
-
 #ifdef HAVE_IFADDRS_H
 # if defined(__ANDROID__)
 #  include "uv/android-ifaddrs.h"

This will make sure that uv_inteface_addresses() will return UV_ENOSYS which makes much more sense then failing as above.

Also would like to know what's your use case of os.networkInterfaces().

neophob commented 2 years ago

Thanks @thunder-coding ! I applied the patch building nodejs:

...
Applying patch: deps-uv-src-unix-core.c.patch
Applying patch: deps-uv-src-unix-net.c.patch       << thats the patch above
Applying patch: deps-uv-src-unix-process.c.patch
Applying patch: deps-uv-uv.gyp.patch
Applying patch: deps-v8-src-flags-flag-definitions.h.patch
Applying patch: deps-v8-src-logging-log.cc.patch
Applying patch: deps-v8-src-trap-handler-trap-handler.h.patch
...

but then the build fails:

  aarch64-linux-android-clang -o /home/builder/.termux-build/nodejs/src/out/Release/obj.target/libuv/deps/uv/src/unix/pthread-fixes.o ../deps/uv/src/unix/pthread-fixes.c '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-D__STDC_FORMAT_MACROS' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D_GLIBCXX_USE_C99_MATH' -I../deps/uv/include -I../deps/uv/src -I/data/data/com.termux/files/usr/include  -Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -g --std=gnu89 -Wall -Wextra -Wno-unused-parameter -Wstrict-prototypes -fno-strict-aliasing -O3 -fno-omit-frame-pointer -fPIC  -MMD -MF /home/builder/.termux-build/nodejs/src/out/Release/.deps//home/builder/.termux-build/nodejs/src/out/Release/obj.target/libuv/deps/uv/src/unix/pthread-fixes.o.d.raw  -I/data/data/com.termux/files/usr/include  -fstack-protector-strong -Oz -c
../deps/uv/src/unix/linux-core.c:636:38: warning: declaration of 'struct ifaddrs' will not be visible outside of this function [-Wvisibility]
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
                                     ^
../deps/uv/src/unix/linux-core.c:637:13: error: incomplete definition of type 'struct ifaddrs'
  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
         ~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
                                     ^
../deps/uv/src/unix/linux-core.c:637:42: error: incomplete definition of type 'struct ifaddrs'
  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
                                      ~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
                                     ^
../deps/uv/src/unix/linux-core.c:639:10: error: incomplete definition of type 'struct ifaddrs'
  if (ent->ifa_addr == NULL)
      ~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
                                     ^
../deps/uv/src/unix/linux-core.c:645:10: error: incomplete definition of type 'struct ifaddrs'
  if (ent->ifa_addr->sa_family == PF_PACKET)
      ~~~^
../deps/uv/src/unix/linux-core.c:636:38: note: forward declaration of 'struct ifaddrs'
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
                                     ^
1 warning and 4 errors generated.
make[1]: *** [deps/uv/libuv.target.mk:141: /home/builder/.termux-build/nodejs/src/out/Release/obj.target/libuv/deps/uv/src/unix/linux-core.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:113: node] Error 2

Also would like to know what's your use case of os.networkInterfaces().

My use case is reuse a nodejs application in a mobile app. the os.networkInterfaces() call if not used directly - BUT there are some parts the use that code. the problem today is the error case which could lead to weird situations

thunder-coding commented 2 years ago

@neophob The following updated patch should work:-

--- ./deps/uv/src/unix/linux-core.c.orig    2022-06-03 12:37:01.127102137 +0530
+++ ./deps/uv/src/unix/linux-core.c 2022-06-03 14:36:13.308341930 +0530
@@ -43,14 +43,6 @@
 #include <fcntl.h>
 #include <time.h>

-#define HAVE_IFADDRS_H 1
-
-#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
-#  undef HAVE_IFADDRS_H
-# endif
-#endif
-
 #ifdef HAVE_IFADDRS_H
 # if defined(__ANDROID__)
 #  include "uv/android-ifaddrs.h"
@@ -640,7 +632,7 @@
   return val;
 }

-
+#ifdef HAVE_IFADDRS_H
 static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
   if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
     return 1;
@@ -654,6 +646,7 @@
     return exclude_type;
   return !exclude_type;
 }
+#endif

 int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
 #ifndef HAVE_IFADDRS_H

And yeah, it's an upstream bug that uv__ifaddr_exclude is compiled even when HAVE_IFADDRS_H is not defined. The updated patch should fix it!

Also, the bug is fixed in libuv 1.44.1. Link to exact commit: https://github.com/libuv/libuv/commit/c40f8cb9f8ddf69d116952f8924a11ec0623b445. So no need to send it upstream, since they've already fixed it on their end :)

neophob commented 2 years ago

Nice, that patch worked.

Now i get a different error: A system error occurred: undefined returned undefined (undefined) with stacktrace:

at Object.networkInterfaces (node:os:264:16)
at userspace js code where os.networkInterfaces() is used
thunder-coding commented 2 years ago

Now i get a different error: A system error occurred: undefined returned undefined (undefined) with stacktrace:

Well that's because your code (or most probably one of your dependencies) hasn't been designed to work in situations where uv_network_interfaces might not be implemented. Can you share the full stack trace, so that the culprit dependency (or your package) can be tracked

neophob commented 2 years ago

Well that's because your code (or most probably one of your dependencies) hasn't been designed to work in situations where uv_network_interfaces might not be implemented.

Not sure if I fully agree, as Nodejs docs say, that os.networkInterfaces() returns an Object (which includes an empty object) - but a system error should not be thrown there.

Can you share the full stack trace, so that the culprit dependency (or your package) can be tracked

that IS the whole usable stacktrace of the code, my function call looks like return os.networkInterfaces();, that's it. Here's the raw stacktrace:

"SystemError [ERR_SYSTEM_ERROR]: A system error occurred: undefined returned undefined (undefined)
    at Object.networkInterfaces (node:os:264:16)
    at E._getInterfaces (/data/data/app.fqdn/files/nodeapp/index.js:1:260599)
    at E.getLanInterface (/data/data/app.fqdn/files/nodeapp/index.js:1:260702)
    at E.getLanAddressIPv4 (/data/data/app.fqdn/files/nodeapp/index.js:1:260898)
    at E.getLanAddress (/data/data/app.fqdn/files/nodeapp/index.js:1:261111)
    at /data/data/app.fqdn/files/nodeapp/index.js:1:326359
    at Layer.handle [as handle_request] (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/layer.js:95:5)
    at next (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/layer.js:95:5)
    at /data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:346:12)
    at next (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:280:10)
    at Function.handle (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:175:3)
    at router (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:47:12)
    at Layer.handle [as handle_request] (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:328:13)
    at /data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:286:9
    at Function.process_params (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:346:12)
    at next (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:280:10)
    at Function.handle (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:175:3)
    at router (/data/data/app.fqdn/files/nodeapp/node_modules/express/lib/router/index.js:47:12)"
neophob commented 2 years ago

is there anything I can do help diagnose this issue? I'm pretty clueless tbh at the moment, any hints are appreciated!

thunder-coding commented 2 years ago

is there anything I can do help diagnose this issue? I'm pretty clueless tbh at the moment, any hints are appreciated!

It seems like you're using a bundler to bundle your application. If you can give me access to the source code of your app, I can certainly look into the place where os.networkInterfaces() is called and whether there is a possible workaround for the same. Best regards, Yaksh.

neophob commented 2 years ago

Yeah that is from the bundled version. Here's a copy of the code that crash

const os = require('os');

<snip>

SystemInfo.prototype._getInterfaces = function() {
  return os.networkInterfaces();  << here the crash happens
};

SystemInfo.prototype.getLanInterface = function() {
  const res = this._getInterfaces();
  return res[this._ifaceNameLan];
};

as you can see, the code is pretty basic and it crashes when the os.networkInterfaces() is used. The crash happens only if the Android targetSDK is set to 30+, it works when targetSDK is set to 28.

neophob commented 2 years ago

Thanks @thunder-coding for your feedback, is my example above enough or is there anything I can do to help you reproducing the problem?

Grimler91 commented 2 years ago

Termux targets sdk level 28 for a reason, so I guess we won't be able to reproduce the issue in termux-app (and therefore @thunder-coding asked for access to the code of your app I guess).

IMHO this issue isn't really termux related. Maybe other nodejs developers can help if you open an issue in their repo

thunder-coding commented 2 years ago

IMHO this issue isn't really termux related. Maybe other nodejs developers can help if you open an issue in their repo

Instead of opening the issue in the nodejs GitHub repo, it'll make more sense to open it in the package's repo which depends on os.networkInterfaces(). Just grep through the node_modules/ directory to find out which package makes use of it.

neophob commented 2 years ago

Termux targets sdk level 28 https://github.com/termux/termux-app/issues/2155, so I guess we won't be able to reproduce the issue.

Yeah, I wanted to bring that issue up for the future (and my use case). Maybe it's my fault thinking that the termux packages support also post SDK 28 devices.

Instead of opening the issue in the nodejs GitHub repo, it'll make more sense to open it in the package's repo which depends on os.networkInterfaces().

This does not make sense as os.networkInterfaces() is a NodeJS API call. There is no reason to use something else from a developers point of view.

stale[bot] commented 2 years ago

This issue/PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

zhoufenqin commented 1 year ago

I also meet the same problem, after some investigation, it was because the node had some problem, and I change a node for my pod then it solved, just share the info for others who may meet the same problem with me.

node:os:68
      throw new ERR_SYSTEM_ERROR(ctx);
      ^

SystemError [ERR_SYSTEM_ERROR]: A system error occurred: uv_interface_addresses returned Unknown system error 13 (Unknown system error 13)    at Object.networkInterfaces (node:os:259:16)
    at getAllIPAddresses (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/newrelic/lib/collector/facts.js:95:25)
    at factMapCb (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/newrelic/lib/collector/facts.js:72:27)
    at /layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:3681:19
    at wrapper (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:271:20)
    at iterateeCallback (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:427:28)
    at /layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:327:20
    at /layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/async/dist/async.js:3679:17
    at onRefreshFinish (/layers/tanzu-buildpacks_new-relic/new-relic-nodejs/node_modules/newrelic/lib/environment.js:609:5)
  code: 'ERR_SYSTEM_ERROR',
  info: {
    errno: 13,
    code: 'Unknown system error 13',
    message: 'Unknown system error 13',
    syscall: 'uv_interface_addresses'
  },
  errno: [Getter/Setter],
  syscall: [Getter/Setter]
}
noonesimg commented 1 year ago

Facing the same problem. Is there any workaround / temporary fix for this? uv_interface_addresses is pretty common node API. Almost any dev server relies on it.

neophob commented 1 year ago

@noonesimg The workaround is to use targets sdk level 28 - let me know if you found another solution

noonesimg commented 1 year ago

@neophob thanks! Can you specify plz, do I need to rebuild the whole termux-app with sdk level 28, or is there a way to just rebuild the nodejs package?

VayuDev commented 11 months ago

For those comming here after trying to use the C++ extension for code-server, I found a workaround:

  1. Format the file with the error with prettier
    1. npm i --global prettier
    2. prettier -w /data/data/com.termux/files/usr/lib/code-server/lib/vscode/out/vs/server/node/server.main.js
  2. Edit /data/data/com.termux/files/usr/lib/code-server/lib/vscode/out/vs/server/node/server.main.js and add befor line 16050 (the line with error, might be another line for you) to:

return '00:00:00:00:00:00';

So the whole function becomes:

function I() {
        return '00:00:00:00:00:00';
        const L = (0, os.networkInterfaces())();
        for (const R in L) { 
        const b = L[R];
                  if (b) {
                    for (const { mac: d } of b) if (a(d)) return d;
                  }
                }
        throw new Error("Unable to retrieve mac address (unexpected format)");
}

I found this out after reading the documentation for os.networkInterfaces() and noticing that this function just returns the first mac address of the first interface in the system. Seems to work for me for now.

twaik commented 1 day ago

Is this still reproducible/relevant?