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

Signal v1.15.0 and newer crash on startup on Fedora Linux 28/29 (and others), libcrypto related during DB operations (induced by sqlcipher binaries) #2634

Open
1 task done
mandree opened this issue Aug 7, 2018 · 46 comments
Labels

Comments

@mandree
Copy link
Contributor

mandree commented Aug 7, 2018

  • I have searched open and closed issues for duplicates

Bug description

Signal crashes on startup with a SIGSEGV.

Steps to reproduce

  1. Build 1.15.2 from source on Fedora Linux 28,
  2. run it.

Actual result:

Gets killed with SIGSEGV. This is the console output:

{"name":"log","hostname":"redacted","pid":6583,"level":30,"msg":"app ready","time":"2018-08-07T23:07:39.573Z","v":0}
{"name":"log","hostname":"redacted","pid":6583,"level":30,"msg":"Ensure attachments directory exists","time":"2018-08-07T23:07:39.581Z","v":0}
{"name":"log","hostname":"redacted","pid":6583,"level":30,"msg":"updateSchema: Current schema version: 0; Most recent schema version: 1; SQLite version: 3.20.1; SQLCipher version: 3.4.2;","time":"2018-08-07T23:07:39.585Z","v":0}
{"name":"log","hostname":"redacted","pid":6583,"level":30,"msg":"updateToSchemaVersion1: starting...","time":"2018-08-07T23:07:39.586Z","v":0}

And then it crashes. This is the backtrace from GDB. If more details are needed, please let me know the magic of Signal's build rig to make it a build with debug symbols. I am a C programmer but unfamiliar with node, yarn, and thereabouts.

#0  0x00007fffe8f0db89 in EVP_MD_CTX_clear_flags () at /lib64/libcrypto.so.1.1
#1  0x00007fffe8efdd21 in EVP_DigestInit_ex () at /lib64/libcrypto.so.1.1
#2  0x00007fffe8f1bc3a in HMAC_Init_ex () at /lib64/libcrypto.so.1.1
#3  0x00007fffd544167a in sqlcipher_openssl_hmac () at /tmp/.org.chromium.Chromium.QBxD7N
#4  0x00007fffd545e245 in sqlcipher_page_cipher () at /tmp/.org.chromium.Chromium.QBxD7N
#5  0x00007fffd5479410 in sqlite3Codec () at /tmp/.org.chromium.Chromium.QBxD7N
#6  0x00007fffd549ac31 in pager_write_pagelist () at /tmp/.org.chromium.Chromium.QBxD7N
#7  0x00007fffd54aa3d0 in sqlite3PagerCommitPhaseOne.part.606 () at /tmp/.org.chromium.Chromium.QBxD7N
#8  0x00007fffd54aa5d1 in sqlite3BtreeCommitPhaseOne.part.607 () at /tmp/.org.chromium.Chromium.QBxD7N
#9  0x00007fffd54c850d in sqlite3VdbeHalt () at /tmp/.org.chromium.Chromium.QBxD7N
#10 0x00007fffd54e0132 in sqlite3VdbeExec () at /tmp/.org.chromium.Chromium.QBxD7N
#11 0x00007fffd54eb9c0 in sqlite3_step () at /tmp/.org.chromium.Chromium.QBxD7N
#12 0x00007fffd542fd11 in node_sqlite3::Statement::Work_Run(uv_work_s*) () at /tmp/.org.chromium.Chromium.QBxD7N
#13 0x00007ffff7cf2dbe in  () at /opt/Signal/libnode.so
#14 0x00007ffff68ed594 in start_thread () at /lib64/libpthread.so.0
#15 0x00007fffefd6e0df in clone () at /lib64/libc.so.6

Expected result:

Proper start up.

Screenshots

Platform info

Signal version:

v1.15.2 as Git tag.

Operating System:

Fedora Linux 28

Linked device version:

8.0.0

Link to debug log

can't obtain one. See above for what I've got.

@scottnonnenberg-signal
Copy link
Contributor

In our @journeyapp/node-sqlcipher dependency, there is a linux build of openssl (libcrypto). Looks like it's the problem, based on that stacktrace. If you want to debug it, you can go to my fork of that dependency and see if you can get it working. Here are my most recent commits: https://github.com/scottnonnenberg-signal/node-sqlcipher/commits/

Thanks for jumping in on this!

@mandree
Copy link
Contributor Author

mandree commented Aug 8, 2018

With the default Signal v1.15.3 from Git (without any node-sqlcipher upgrades), I get this - the ctx=0x0 looks suspicious to me, since the manual page states:
"EVP_DigestInit_ex() sets up digest context ctx to use a digest type from ENGINE impl. ctx must be initialized before calling this function. type will typically be supplied by a function such as EVP_sha1(). If impl is NULL then the default implementation of digest type is used."

I still can't make head or tails of this since I don't know how/where/why these are called.

#0  0x00007fffe8f0db89 in EVP_MD_CTX_clear_flags (ctx=ctx@entry=0x0, flags=flags@entry=2) at crypto/evp/evp_lib.c:479
#1  0x00007fffe8efdd21 in EVP_DigestInit_ex (ctx=0x0, type=0x7fffe9225cc0 <sha1_md>, impl=0x0) at crypto/evp/digest.c:66
#2  0x00007fffe8f1bc3a in HMAC_Init_ex (ctx=0x28eac331a360, key=<optimized out>, len=<optimized 
out>, md=<optimized out>, impl=0x0) at crypto/hmac/hmac.c:70
...

@richardschuetz
Copy link

As can be seen from the stacktrace, the system's OpenSSL 1.1.0 library is used instead of the statically linked one. This can happen if the library is already loaded into the Electron process and its symbols take precedence. The crash is likely a result of SQLCipher expecting the older version of OpenSSL it was built against.

@scottnonnenberg-signal You can prevent this by compiling your version of libcrypto.a with hidden symbol visibility (e.g. ./Configure linux-x86_64 no-shared -fPIC -fvisibility=hidden). Including precompiled code from unknown sources in a so-called private messenger is highly debatable, though.

@mandree
Copy link
Contributor Author

mandree commented Aug 10, 2018

@scottnonnenberg-signal I think the approach of packing a static OpenSSL on Linux is not working for me although I understand it is trying to be helpful.

Basically we should not be mixing SSL stuff in the same program, and up to the lastest v1.14.x things went smoothly for me.

I am not sure if @richardschuetz 's proposal is right, the only way I have found through experimenting for hours on end is this script (snippet):

yarn add --force electron@2.0.7 @journeyapps/sqlcipher
yarn add electron-rebuild --dev
yarn generate
node_modules/.bin/electron-rebuild -f -w @journeyapps/sqlcipher
NODE_ENV=production NODE_APP_INSTANCE=production yarn run start

I can not package this build through yarn build-release --linux rpm though, which will rebuild sqlcipher in a different manner and then fail at run-time, not with SIGSEGV, but through not finding libcrypto.so.1.0.0. It appears it picks up a binary from journeyapps in this case, since that tries to bind against libcrypto.so.1.0.0. - I don't have that decrepit version on my system (Fedora 28).

I cannot yet your sqlcipher fork to work at all, the original one requires the rebuild-from-source as shown above.

@scottnonnenberg-signal
Copy link
Contributor

@mandree That's not the right version of @journeyapps/sqlcipher - Signal Desktop uses a forked version of it because the version you've installed downloads a precompiled binary which is indeed linked against a very old version of libcrypto.

@stemid
Copy link

stemid commented Aug 10, 2018

@richardschuetz where do you run this Configure line you mention? I use a spec file to build an RPM of signal-desktop for myself on Fedora 27 and I can't see where I'd insert this Configure line.

The %build part looks like this in my spec file.

%build
cd Signal-Desktop-%{version}
sed -i -- "s/    \"node\": .*/    \"node\": \"$(node -v | cut -b 2-)\"/g" package.json
PATH=node_modules/.bin:$PATH yarn install

yarn install --frozen-lockfile
yarn generate --force
yarn prepare-beta-build
yarn build-release --linux dir

I also get segfault but even in the latest 1.15.3 version. I tried going back to 1.15.1 and still get segfault. Also tried removing my .config/Signal dir but that didn't help. The last version I can successfully build and run with my RPM spec file is 1.14.4. They all build but only 1.14.4 runs without segfault.

@mandree
Copy link
Contributor Author

mandree commented Aug 11, 2018

@scottnonnenberg-signal what I am trying to do is build Fedora 28 packages of Signal for several computers I oversee and deploy it.

A statically linked obsolete OpenSSL version from Ubuntu 14.04 appears not to work on Fedora 28 (or Arch for that matter) for various reasons: they do not blend in with a different distribution that uses different policies, versions, paths, and possibly other reasons.

So IMO what I/we need to do is rebuild sqlcipher all from source, link dynamically against the system's OpenSSL library (as the original journeyapps/sqlcipher claims to do) and forbid it to use any precompiled binaries. The electron-rebuild run on the original sqlcipher exacts just that for the "yarn run start", but if I run yarn build-release, it clobbers the results of the electron-rebuild, rebuilds sqlcipher again (pulling in the binary) and then boom.

Bottom line, I want to recompile sqlcipher and waive any binaries
- how do I do that? Fork sqlcipher again and remove all binaries? Or is there an easier way through signal's configuration?

@mandree
Copy link
Contributor Author

mandree commented Aug 11, 2018

Success. Following up my own post, after researching, reading, experimenting, learning, I have achieved my goal.

I have ended up using the original @journeyapps/sqlcipher, hack its "install" configuration in package.json to --build-from-source, install the hacked module as requisite.

My build script for Fedora 28 currently used as shown below, works with v1.15.4 and generates a functioning app that is dynamically linked against libcrypto.so.1.1. I understand that may not be good for distribution, but the same approach should satisfy anything that builds from source and goes shipwrecked by the statically linked Ubuntu 14.04 OpenSSL crap.

WARNING this is not for developers who hack on Signal due to the brutal git reset --hard/git clean below, it will clobber any and all of your changes! It is to do a clean rebuild from a Git release tag.

#!/bin/sh
# Shell script to rebuild Signal from scratch.
# Assumes that the Git tree is checked out on a release tag,
# as it talks to the production servers.
#
# Tested on Fedora 28 with Signal v1.15.4 from Git.
#
# Requires yarn, and jq <https://stedolan.github.io/jq/>.
#
# © 2018 Matthias Andree. GNU GPL v2 or later.

### ADJUST THIS TO WHERE THE CHECKOUT IS ###
DIR="$HOME/VCS-other/signal-desktop.git"

### NO USER SERVICEABLE PARTS BELOW ###
set -ex
cd "$DIR"

# revert to a clean Git checkout
git reset --hard
git clean -fdxq -e release

# update electron, security fix time
yarn add --dev electron@~2.0.3  # electron-rebuild 

# patch @journeyapps/sqlcipher to nuke binaries
# try and use a local copy of sqlcipher based on the original one
yarn add --force @journeyapps/sqlcipher
d=.tmp-ja-sqlc
rm -rf "$d"
mkdir "$d"
cp -pR node_modules/@journeyapps/sqlcipher "$d"
jq \
	'del(.bundledDependencies)|. * {"scripts":{"install":"node-pre-gyp install --build-from-source"}}' \
	$d/sqlcipher/package.json  >.$$ \
    && mv .$$ $d/sqlcipher/package.json
# purge cache just in case (we didn't change version)
rm -rf $(yarn cache dir)/npm-@journeyapps/sqlcipher-*
yarn add --force file://$(realpath $d/sqlcipher)

# build
yarn generate

yarn --verbose build-release --linux rpm
ls -lbdtr release/*.rpm

# now run the thing:
NODE_ENV=production NODE_APP_INSTANCE=production yarn run start & disown $!

(side RANT: Note that Ubuntu "long-term-support" is a red herring, it only applies to a few dozen base packages that are core to ubuntu server, on the Desktop it's useless as most packages go out of support after a few months, and we should not encourage users to use privacy/security-sensitive stuff on top of a rocking and sliding pile of unmaintained packages. Don't build on Ubuntu 14.04. It enhances compatibility but only permits users to stay on their outdated/insecure installs longer.)

@mandree mandree changed the title v1.15.2 crashes on startup on Fedora Linux 28, crypto related during DB Signal v1.15.(0...4) crashes on startup on Fedora Linux 28 (and others), libcrypto related during DB operations (induced by sqlcipher binaries) Aug 11, 2018
@duckinator
Copy link

Reproduced with Signal v1.15.5 on Fedora 28, building from the zip file linked to on https://github.com/signalapp/Signal-Desktop/releases/tag/v1.15.5 .

@Vaelatern
Copy link

Reproduced on a LibreSSL-based Void Linux system.
If it at least had a binary, then our checks would direct any looking for libcrypto.so to the correct lib, but this seems to be done (hopefully accidentally) to require a very specific library name and version.

@Vaelatern
Copy link

It should be noted that "So the Signal-Desktop build uses a fork of this project," instead of the upstream for node-sqlcipher. journeyapps/node-sqlcipher#8

@d-hansen
Copy link

FWIW: the above steps of patching @journeyapps/sqlcipher (and performed in principal) worked for 'git checkout tags/v1.17.2'.

@fholzer
Copy link

fholzer commented Feb 23, 2019

Unfortunately @mandree's shell script no longer works because the node-sqlcipher fork Signal is using added support for FTS5, which isn't present in the original. I created journeyapps/node-sqlcipher#17 to get it added to the original package.

@mandree
Copy link
Contributor Author

mandree commented Mar 6, 2019

I found https://copr.fedorainfracloud.org/coprs/luminoso/Signal-Desktop/ (and rebuilt the RPMs on F29 from commit 6cd8e8411), which seems to work on F29. The .spec file can be browsed at https://copr-dist-git.fedorainfracloud.org/cgit/luminoso/Signal-Desktop/signal-desktop.git/tree/signal-desktop-arch.spec?h=f29&id=6cd8e8411c58c19cf9154da0eafa64fb1f5450ff and it appears to work for me. So I wonder if there's an easier approach than fixing my build script... it would be good though if Signal could be built OOTB without any further patching.

@fholzer
Copy link

fholzer commented Mar 6, 2019

Once journeyapps/node-sqlcipher#17 is merged the Signal maintainers could switch back to from the fork they're currently using. The fork links statically against libcrypto which is causing issues with a number of distributions.

Edit: typo

@mandree
Copy link
Contributor Author

mandree commented Mar 29, 2019

@fholzer
Copy link

fholzer commented Mar 29, 2019

Yeah, i noticed. We'll need to wait for a new version to be published to npm...

Edit:
Actually no, the dependency is pointing to some github repo at the moment anyway, so I guess that's OK. So Signal just needs to update their package.json.

Edit2:
Nevermind.

  • revert all local changes
  • change engine to your node version in package.json
  • change sqlcipher dependency to https://github.com/journeyapps/node-sqlcipher.git#ead1555c7c3abab7eebdf6cb9b79bdbde4aece6e in package.json
  • if you distro uses rpm: replace "deb" with "rpm" in build "target" array in package.json
  • build from source
  • enjoy

👍

(FYI i had to clear my ~/.cache/Signal directory to make it work)

@stemid
Copy link

stemid commented Mar 31, 2019

@fholzer which version did you try that with? I did it with v1.23.1 but it crashed at startup.

$ NODE_ENV=production NODE_APP_INSTANCE=production yarn run start & disown $!                                                                                                                   
[1] 11123                                                                                                                                                                                                                             
yarn run v1.15.2
$ electron .
Set Windows Application User Model ID (AUMID) { appUserModelId: 'org.whispersystems.signal-desktop' }
NODE_ENV production
NODE_CONFIG_DIR /home/stemid/src/Signal-Desktop/config
NODE_CONFIG {}
ALLOW_CONFIG_MUTATIONS undefined
HOSTNAME undefined
NODE_APP_INSTANCE undefined
SUPPRESS_NO_CONFIG_WARNING undefined
userData: /home/stemid/.dotfiles/.config/Signal
config/get: Did not find user config file, cache is now empty object
config/get: Did not find ephemeral config file, cache is now empty object
making app single instance
App threw an error during load
TypeError: app.requestSingleInstanceLock is not a function
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/main.js:101:23)
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/main.js:990:3)
    at Module._compile (module.js:642:30)
    at Object.Module._extensions..js (module.js:653:10)
    at Module.load (module.js:561:32)
    at tryModuleLoad (module.js:504:12)
    at Function.Module._load (module.js:496:3)
    at loadApplicationPackage (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:287:12)
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:328:5)
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:365:3)
Unhandled Error: TypeError: app.requestSingleInstanceLock is not a function
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/main.js:101:23)
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/main.js:990:3)
    at Module._compile (module.js:642:30)
    at Object.Module._extensions..js (module.js:653:10)
    at Module.load (module.js:561:32)
    at tryModuleLoad (module.js:504:12)
    at Function.Module._load (module.js:496:3)
    at loadApplicationPackage (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:287:12)
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:328:5)
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:365:3)
Unhandled Error
TypeError: app.requestSingleInstanceLock is not a function                                                                                                                                                                             
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/main.js:101:23)                                                                                                                                                             
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/main.js:990:3)                                                                                                                                                              
    at Module._compile (module.js:642:30)                                                                                                                                                                                              
    at Object.Module._extensions..js (module.js:653:10)                                                                                                                                                                                
    at Module.load (module.js:561:32)                                                                                                                                                                                                  
    at tryModuleLoad (module.js:504:12)                                                                                                                                                                                                
    at Function.Module._load (module.js:496:3)                                                                                                                                                                                         
    at loadApplicationPackage (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:287:12)                                                                                                   
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:328:5)                                                                                                        
    at Object.<anonymous> (/home/stemid/src/Signal-Desktop/node_modules/electron/dist/resources/default_app.asar/main.js:365:3)                                                                                                        
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

@mandree
Copy link
Contributor Author

mandree commented Mar 31, 2019

Arch Linux are using a patch to link libcrypto dynamically rather than statically - this appears to fix crashes for me on Fedora 29, too. Link:
https://aur.archlinux.org/cgit/aur.git/tree/openssl-linking.patch?h=signal

@fholzer
Copy link

fholzer commented Mar 31, 2019

@stemid I'm on 1.22.0 at the moment. Had some issues with 1.23.x myself, but no time to look into it in more detail yet.

@mandree not sure which sqlcipher package Arch uses, but the file that seems to get patched with the file you linked is actually linking dynamically already: https://github.com/journeyapps/node-sqlcipher/blob/master/deps/sqlite3.gyp#L75
Maybe I missed something?

@mandree
Copy link
Contributor Author

mandree commented Mar 31, 2019

@mandree not sure which sqlcipher package Arch uses, but the file that seems to get patched with the file you linked is actually linking dynamically already: https://github.com/journeyapps/node-sqlcipher/blob/master/deps/sqlite3.gyp#L75
Maybe I missed something?

@fholzer as of v1.23.1, sqlcipher isn't pulled from in its master branch, but from a frozen version of Scott Nonnenberg's clone:

$ grep node-sqlcipher * 2>/dev/null
package.json:    "@journeyapps/sqlcipher": "https://github.com/scottnonnenberg-signal/node-sqlcipher.git#2e28733b61640556b0272a3bfc78b0357daf71e6",
yarn.lock:"@journeyapps/sqlcipher@https://github.com/scottnonnenberg-signal/node-sqlcipher.git#2e28733b61640556b0272a3bfc78b0357daf71e6":
yarn.lock:  resolved "https://github.com/scottnonnenberg-signal/node-sqlcipher.git#2e28733b61640556b0272a3bfc78b0357daf71e6"

@stemid
Copy link

stemid commented Apr 1, 2019

@fholzer thanks for that but it failed during yarn install. Tried it with a new git repo, your mods.

Output: https://bpaste.net/show/9fc922f28d05

Fedora 28 with node and node-gyp installed from packages. Maybe I need later versions of those?

@fholzer
Copy link

fholzer commented Apr 1, 2019

@stemid not entirely sure what to make of this... have you had a look at nodejs/node-gyp#809? there's one comment in particular that seemed to have help a lot of ppl, maybe give that a try? nodejs/node-gyp#809 (comment)

In case that doesn't help, can you run make BUILDTYPE=Release -C build in ./node_modules/@journeyapps/sqlcipher/? I'm curious about the output.

Fedora 28 with node and node-gyp installed from packages. Maybe I need later versions of those?

That's a possibility, though I'm no expert in regards to compiling native node modules. Some ppl suggested outdated vars in ~/.npmrc in the thread I linked. Not sure... sorry
Here's what I'm running:

Signal-Desktop$ node -v
v10.15.0
Signal-Desktop$ npm -v
6.9.0
Signal-Desktop$ yarn -v
1.9.4
Signal-Desktop$ npx node-gyp -v # this should be installed by Signal
v3.8.0

Have you ever successfully built Signal with your setup? (sqlcipher in particular)

@ckujau
Copy link

ckujau commented Apr 20, 2019

The patch from comment 478328776 worked for me, but applying could only be done after the first yarn install, and then my nodejs binary from Fedora 29 was too new, so stringing all this together, here is how I got Signal-Desktop running again:

wget "https://aur.archlinux.org/cgit/aur.git/plain/openssl-linking.patch?h=signal" -O ~/openssl-linking.patch
sed -i.bak "s/node\": \"10.13.0/node\": \"$(node --version | sed 's/v//')/" package.json

yarn install --frozen-lockfile
patch -p1 < ~/openssl-linking.patch 
sudo chattr +i node_modules/@journeyapps/sqlcipher/deps/sqlite3.gyp      # Err...

yarn generate
SIGNAL_ENV=production yarn build-release
NODE_ENV=production NODE_APP_INSTANCE=production yarn run start --disable-gpu

Still, this bug is open for way too long and I don't understand why Signal desktop should only be a thing for MacOS or Windows users, especially considering most tinfoil hats (hello, myself!) would run Linux anyway. This report even includes fixes, can't they just be applied to upstream to finally resolve this one?

@stemid
Copy link

stemid commented Apr 22, 2019

@ckujau
This method worked for me on F28 with v1.24.1! Thank you so much. I haven't seen Signal-desktop running for almost a year now, iirc.

I only skipped the chattr line.

@brian-provenzano
Copy link

Still, this bug is open for way too long and I don't understand why Signal desktop should only be a thing for MacOS or Windows users, especially considering most tinfoil hats (hello, myself!) would run Linux anyway. This report even includes fixes, can't they just be applied to upstream to finally resolve this one?

I agree this is why I just gave up on Signal... I can't see why they cannot take this info (or info in multiple threads in regards to RPMs/Fedora functionality) and create a build.

@mandree
Copy link
Contributor Author

mandree commented Apr 22, 2019

I agree this is why I just gave up on Signal... I can't see why they cannot take this info (or info in multiple threads in regards to RPMs/Fedora functionality) and create a build.

I haven't tested these builds, but it appears there's a COPR:

@brian-provenzano
Copy link

I haven't tested these builds, but it appears there's a COPR:

Yeah I've seen these. Thing is if I am using a security application I want it built and provided by the company producing it.

@hsanjuan
Copy link

hsanjuan commented Jan 8, 2020

The snap-packaged application is also broken because of this, along with openSUSE Tumbleweed. Maybe when Signal sigfaults in absolutely every Linux distro something will be done about it?

grebe added a commit to grebe/Signal-Desktop that referenced this issue Feb 3, 2020
Signal is currently using a forked version of node-sqlcipher. I'm not
entirely sure as to all the motivations for forking, but it seems that
one reason may have been because upstream didn't support FTS5. This
reason is no longer relevant because of this PR [^1], which adds FTS5
support upstream.

Another reason for the forked version of node-sqlcipher may be to bundle
libcrypto. This is causing problems with many Linux users, especially
those who are not using Ubuntu [^2][^3]. It seems to me that statically
linking is not generally considered to be a best practice on Linux. The
upstream project's README [^4] seems to have a sensible policy: bundling
OpenSSL on Windows and OS X platforms and dynamically linking to the
system's library on Linux platforms.

This PR moves away from the forked node-sqlcipher and returns back to
upstream. This seems to fix OpenSSL problems on non-Ubuntu Linux
distributions.

[^1]: journeyapps/node-sqlcipher#17
[^2]: signalapp#2634
[^3]: signalapp#2662
[^4]: https://github.com/journeyapps/node-sqlcipher#openssl
@buscher
Copy link

buscher commented Feb 20, 2020

Hello!

I have a crashing Signal too, my backtrace looks similar to the initial posted.
Lets me try to sum up my investigations and please correct me once you spot the error.

  • Signal crashes in libcrypto.so EVP_MD_CTX_clear_flags
  • Signal has no direct dependencies to libcrypto.so (confirmed by objdump -p /opt/Signal/signal-desktop | grep NEEDED, I am not using ldd to only show the direct dependencies)
  • Signal depends on libgio-2.0.so (again confirmed by objdump -p /opt/Signal/signal-desktop | grep NEEDED)
  • libgio-2.0.so.0 depends on libmount.so.1
  • libmount.so.1 depends on libcryptsetup.so.12 (needed for my disc encryption)
  • libcryptsetup.so.12 depends on libcrypto.so.1.1 (openssl-1.1.1d)
  • Signal uses the symbols from libcrypto.so.1.1 and not its own symbols and crashes

This is the scenario on my laptop. Gentoo btw.
On my desktop (also Gentoo), it works fine, because I do not have any disc encryption. libmount.so.1 does not depend on libcryptsetup.so.12 in this case, no cryptsetup compiled in.

Conclusion: Signal can not be used Linux installations with (encrypted fs and) cryptsetup with OpenSSL backend?

OR

Hypothesis: Signal can be used on Linux installations with cryptsetup with OpenSSL backend IF they match the OpenSSL version used in the Signal version?
Question: which OpenSSL version is used in Signal?

or is there any other workaround which I missed? :)
or am I totally wrong here and did not understand the ticket at all?

@hsanjuan
Copy link

@buscher workaround is patching one of the dependencies (see above #2634 (comment))

@bprfh
Copy link

bprfh commented Feb 23, 2020

@buscher as hsanjuan said, you have to either patch a dependency, or replace the dependency
If you want, you can use this script to replace the dependency and build it automatically:
#!/bin/bash
source ~/.bashrc
rm -rf "./Signal-Desktop"
git clone https://github.com/signalapp/Signal-Desktop.git
cd Signal-Desktop
sed 's/"@journeyapps\/sqlcipher.*/"@journeyapps\/sqlcipher": "4.0.0",/g' package.json package.json.tmp && mv package.json.tmp package.json
nvm use
if hash nvm 2>/dev/null; then
nvm use
else
echo "Warning, no NVM found, you need to have the exact node version installed"
fi
yarn install
yarn grunt
yarn icon-gen
yarn build-release

After that you can start the binary from the signal/release/linux-unpacked directory

@mandree
Copy link
Contributor Author

mandree commented Mar 24, 2020

@scottnonnenberg-signal can this issue please be addressed in the next release? It's been open for one and a half years and the cause is known.

To all other users: please refrain from posting "me too" with just changed minor details of solutions, the cause and its workaround are sufficiently documented already. If in doubt whether your information is already contained here, the slightest doubt => do not post comments here.

@scottnonnenberg-signal
Copy link
Contributor

@mandree We don't officially support any Linux platform other than Debian-based Linux distributions, via our official apt packages. We welcome assistance in making Signal Desktop more accessible to other distributions, but right now we can't spend much time on it. And we won't be changing our SQLCipher/OpenSSL build approach, statically linking everything.

So the best way to help us is to research then provide low-impact changes we could apply to our existing setup.

@bprfh
Copy link

bprfh commented Mar 24, 2020

@scottnonnenberg-signal Sorry to jump in like this, but I think there is misconumication

Currently you can't run signal on any linux distribution except ubuntu. This is because your forked version of sqlcipher links against a static openssl library.

The solution would be to either change your forked sqlcipher repository to not link against a static openssl, or use the upstream one.
I can gladly do a pull request for that but I don't know why you forked the sqlcipher repository and don't use the upstream one, so I don't think that would be the solution.

To be clear:
If you replace the line 65 in package.json:
"@journeyapps/sqlcipher": "https://github.com/scottnonnenberg-signal/node-sqlcipher.git#b10f232fac62ba7f8775c9e086bb5558fe7d948b",
With:
"@journeyapps/sqlcipher": "4.0.0",
Signal builds and runs fine on Fedora, in fact I run it this way.

@scottnonnenberg-signal
Copy link
Contributor

Currently you can't run signal on any linux distribution except ubuntu. This is because your forked version of sqlcipher links against a static openssl library.

This is not correct. I've tested Signal Desktop successfully not just on Ubuntu, but also Debian. And Linux Mint, and Kubuntu, a step or two away from Ubuntu itself. Perhaps you haven't tried with the most recent builds?

@bprfh
Copy link

bprfh commented Mar 24, 2020

My apologizes, did you change anything regarding sqlcipher?
The build succeeds from source right now for me.
Last failed rebuild should be either around 23.02.2020 or a signal version earlier on fedora 31

Could somebody else comment if it stills fails for them?

@lnicola
Copy link

lnicola commented Mar 24, 2020

Arch patches the openssl dependency: https://git.archlinux.org/svntogit/community.git/tree/trunk/openssl-linking.patch?h=packages/signal-desktop.

@d-hansen
Copy link

My apologizes, did you change anything regarding sqlcipher?
The build succeeds from source right now for me.
Last failed rebuild should be either around 23.02.2020 or a signal version earlier on fedora 31

Could somebody else comment if it stills fails for them?

My guess would be that it builds (for now) due to this commit (updating the forked version of node-sqlcipher to 4.3.0 and updates the "packaged" openssl library to 1.1.1d: scottnonnenberg-signal/node-sqlcipher@b10f232

@hsanjuan
Copy link

My guess would be that it builds (for now)

This was not a build problem. It always built. The problem is the application died on start. I checked and it seems to run fine now that openssl was updated to 1.1.1d (openSUSE Tumbleweed).

I don't know why you forked the sqlcipher repository and don't use the upstream one

It seems the upstream does not include a statically-linked openssl for linux and is more outdated. Now, are those compiled by hand on a dev machine? If so, it seems there is a small dilemma here between using manually compiled binaries by a project dev vs. using the distribution's provided libraries.

@mandree
Copy link
Contributor Author

mandree commented Mar 26, 2020

Quoting @d-hansen:

My guess would be that it builds (for now) due to this commit (updating the forked version of node-sqlcipher to 4.3.0 and updates the "packaged" openssl library to 1.1.1d: scottnonnenberg-signal/node-sqlcipher@b10f232

For me, 68ee557 apparently fixes the issue on Fedora 31 (i. e. v1.32.0-beta.2 and younger), yet I'd like to stress @d-hansen's "for now".

My concern is that the error will come back as OpenSSL is updated again in the distros over time on Linux. It would seem that working now is just a coincidence because .../node_modules/@journeyapps/sqlcipher/build/Release/obj/gen/sqlcipher-amalgamation-3030001/OpenSSL-Linux/libcrypto.a is 1.1.1d which happens to match the system-installed openssl-1.1.1d-2.fc31.x86_64.

Given that electron at least on Linux links to libcrypto.so dynamically (see below), it seems important that we prevent ever mixing a different version in, so I ask @scottnonnenberg-signal to
please consider linking libcrypto dynamically for sqlcipher:

Downstream packagers have been patching node_modules/@journeyapps/sqlcipher/deps/sqlite3.gyp to replace Linux's '<(SHARED_INTERMEDIATE_DIR)/sqlcipher-amalgamation-<@(sqlite_version)/OpenSSL-Linux/libcrypto.a' by -lcrypto and possibly also ditching the openssl-include dir from the sqlcipher-amalgamation, and that appears to have worked.

This is on Fedora 31 amd64:

$ ldd node_modules/electron/dist/electron | grep crypto
	libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f24b4d00000)
	libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f24b4a07000)

@d-hansen
Copy link

It is very nonsensical to me to have a product that touts security (of your messages) but then does not follow or track the latest updates to highly-vulnerable cryptography libraries. One would think that a product like signal would want to stay as current as possible and track the most recent versions and updates to OpenSSL and libcrypto specifically! Using a version of node/sqlcipher from 2 years ago (with fairly minimal updates) and then statically linking against libcrypto from a particular version of OpenSSL just seems so wrong in the security world. We want systems to quickly respond to CVE's. So, it likely won't be very long until the next rev of OpenSSL is released and of course, systems like Fedora, Ubuntu, etc are going to quickly upgrade to it. :(

@lnicola
Copy link

lnicola commented Mar 27, 2020

Not only that, but the encryption key is stored next to the database, while the attachments are unencrypted. I don't understand what scenario the encryption mitigates.

@mandree
Copy link
Contributor Author

mandree commented Mar 27, 2020

@scottnonnenberg-signal

@mandree We don't officially support any Linux platform other than Debian-based Linux distributions, via our official apt packages. We welcome assistance in making Signal Desktop more accessible to other distributions, but right now we can't spend much time on it. And we won't be changing our SQLCipher/OpenSSL build approach, statically linking everything.

So the best way to help us is to research then provide low-impact changes we could apply to our existing setup.

Scott, I understand time constraints, but I do not understand what the technical merit of "linking statically" is if it breaks portability. But then we need to do two things:

  1. Linking statically, you as maintainers must update to each and every security release of OpenSSL affecting libcrypto and re-release Signal. This is all but low-profile. Given the past interval of how rarely sqlcipher's reference in signal-desktop has changed, I'd say that linking libcrypto.a should be discontinued because that effort has not been sustained (see @d-hansen's comment above)
  2. For other distros, we would have to identify which packages have been built with different options on non-Ubuntu-LTS-distros and might pull in libcrypto.so, as happens on Fedora, and then modify or replace these. This is also everything, but not low-profile.

The proper course of action would seem to declare Ubuntu 16 unsupported and require a dynamic libcrypto.so.1.1 for now and build against 1.1 headers.

What currently happens is that some part of the build on Fedora (included module) pulls in libcrypto.so (as seen by my ldd screenshot) dynamically, and your sqlcipher pulls in libcrypto.a from a different source statically. This can cause symbols to be mixed from different library sources by linkers, and is technically unsound, is likely what caused the wreck on Fedora 28+ before 1.32. And that is why downstream packagers are switching to dynamic linking of libcrypto.

The given low-profile change is this:
https://copr-dist-git.fedorainfracloud.org/cgit/luminoso/Signal-Desktop/signal-desktop.git/tree/signal.spec?id=5eab5275fab96abc9c55644cc2d1eb0f041fc38c#n64

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

No branches or pull requests