Public bug reported:

Background:
NodeJS has a native extension API: https://nodejs.org/api/addons.html
It's fairly understood by developers that NodeJS's ABI is stable, and that one 
module built using a version of nodejs should work on another semantically 
version compatible of nodejs.

NodeJS exposes various third party libraries to the native module
developers. Quote from the addons developers page: "Node.js includes a
number of other statically linked libraries including OpenSSL. These
other libraries are located in the deps/ directory in the Node.js source
tree. Only the libuv,i OpenSSL, V8 and zlib symbols are purposefully re-
exported by Node.js and may be used to various extents by Addons."

It's fairly understood by developers that native modules have the same
ABI guarantee than the rest of the node API.

The NodeJS ecosystem uses native modules extensively, and it's fairly
common for developers to publish precompiled versions of their
extensions so that the typical end-user can simply npm install their
dependencies without worrying about having a compiler installed. Some
packages will do their own thing (see for instance
https://www.npmjs.com/package/uws), while others will rely on third
party extensions to facilitate their work. See for instance prebuild
(https://www.npmjs.com/package/prebuild) that has a handful of
dependents, or node-pre-gyp (https://www.npmjs.com/package/node-pre-gyp)
that has north of 350 dependents. So the nodejs ecosystem has roughly
400 native packages that are publishing prebuilt versions of their
extensions.

Problem with the Ubuntu nodejs package:
Put simply, it breaks prebuilt packages that depend on OpenSSL. NodeJS 8.10.0 
officially comes with OpenSSL 1.0.2n, while the NodeJS 8.10.0 that comes with 
the Ubuntu package exposes OpenSSL 1.1.0g.

Since there are ABI breakages between OpenSSL 1.0.2 and 1.1.0, these ABI
breakages are bubbling up to any prebuilt native addon.

Here is an example:

https://github.com/nicolasnoble/openssl-nodejs-ubuntu-demo

If you build this package under the mainline nodejs, it will try to import the 
following symbols from OpenSSL 1.0.2:
 . SSL_library_init
 . SSLeay_version

Whereas if you build it under Ubuntu's nodejs, it will try to import the 
following symbols instead from OpenSSL 1.1.0:
 . OPENSSL_init_ssl
 . OpenSSL_version

Therefore, trying to load one prebuilt module from one version of the
runtime to another will result in a symbol loading error:

node: symbol lookup error: /home/pixel/node-openssl-addon-
example/build/Release/openssl_example.node: undefined symbol:
SSL_library_init

Incidentally, nodejs 10.5.0 uses OpenSSL 1.1.0h, and compiling the same
demo module with this version of node will try to import the proper
symbols. Obviously, since the module will be built for the wrong version
of the nodejs runtime, it won't load, but the SSL symbols are now
proper.

This creates weird bug reports for nodejs extension developers, such as
https://github.com/grpc/grpc-node/issues/341

Another example is uws. Trying to use uws in ubuntu's nodejs will result
in the same sort of failures. Which means there are at least two
packages available out there that are affected by this issue.


I don't think this is easily solvable, and all of my suggestions for fixing it 
have severe cons. Ubuntu won't want to downgrade their system's OpenSSL for 
this. Maybe there's a way to get another openssl package for 1.0.2, and have 
the nodejs runtime for Ubuntu depend on it. Another possible solution would be 
to radically upgrade nodejs to 10, so that the ABI of OpenSSL will then match 
properly. But this may be viewed as a too radical upgrade.

One sort of mitigation option would be to get node-pre-gyp and prebuild
to recognize that it's running with this version of the nodejs runtime,
so that it can recognize and take actions, such as downloading an
ubuntu-specific version of the prebuilt extension, or recompiling from
sources. This obviously would help mitigating the issue for a good
portion of existing packages that are using node-pre-gyp and prebuild,
but for packages that are doing their own thing such as uws, this
solution wouldn't work properly.

ProblemType: Bug
DistroRelease: Ubuntu 18.04
Package: nodejs 8.10.0~dfsg-2
ProcVersionSignature: Ubuntu 4.15.0-24.26-generic 4.15.18
Uname: Linux 4.15.0-24-generic x86_64
ApportVersion: 2.20.9-0ubuntu7.2
Architecture: amd64
CurrentDesktop: ubuntu:GNOME
Date: Tue Jul  3 05:34:28 2018
EcryptfsInUse: Yes
InstallationDate: Installed on 2017-03-08 (482 days ago)
InstallationMedia: Ubuntu 16.10 "Yakkety Yak" - Release amd64 (20161012.2)
ProcEnviron:
 TERM=xterm-256color
 PATH=(custom, no user)
 XDG_RUNTIME_DIR=<set>
 LANG=en_US.UTF-8
 SHELL=/bin/bash
SourcePackage: nodejs
UpgradeStatus: Upgraded to bionic on 2018-05-10 (54 days ago)

** Affects: nodejs (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: amd64 apport-bug bionic

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1779863

Title:
  Ubuntu nodejs package isn't ABI compatible with mainline nodejs.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/nodejs/+bug/1779863/+subscriptions

-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to