bepaald / signalbackup-tools

Tool to work with Signal Backup files.
GNU General Public License v3.0
790 stars 38 forks source link

Repacking backup leads to full memory and complete crash of computer #122

Closed hillbicks closed 1 year ago

hillbicks commented 1 year ago

Hi there,

first of all, thanks for providing this app!

Now, I reinstalled my Pixel5 with the original firmware yesterday, took a backup beforehand. The backup is 13GB in size. When trying to import it, if fails with malformed data. chats are completely missing, only groups (empty) show up.

After looking at the database I found one foreign key violation, cleaned it up ( according to the guides linked in other issues) to the best of my knowledge. When trying to repack it, the computer freezes within 10 - 20 seconds.

I have a lenovo p14s with AMD Ryzen 4750 and 16GB RAM and 20GB of swap.

After the third try I looked at the system usage and memory consumption rises until the PC becomes unresponsive. Last step is always during the attachment phase. Unfortunately I can not provide any logfiles since I have to do a hard shutdown.

I'm using arch btw :p

I'm looking into ways to limit the memory of the process, maybe do it in a VM. Anything else I can provide or do?

Thanks!

PS: the only memory issue I found is #24

bepaald commented 1 year ago

Thanks for your report! I already had written up a long reply, expressing my confusion, but I think I found a bug (or I should say you found a bug).

May I assume you have exported the database to a directory, made your changes to the sql database, and are now repacking that directory into a backup file? I just realized that in this situation, the entire directory contents (13GB in you case) are read into memory. I don't remember why I do it like this, it doesn't seem efficient, so (until I find out I had to do it like that) I'm considering this a bug.

In the meantime, if you remember the commands you used to fix the database, a workaround is to run your fixes on the backup file directly: signalbackup-tools [input] [passphrase] --runsqlquery "DELETE FROM somewhere WHERE _id = something" --runsqlquery "another query, as many as you want" -o [output]. Running it like this, the program really should not ever exceed ~200MB RAM usage.

If you were already running on the backup file directly (not on a directory) when you saw this problem, let me know, we'll need to investigate.

hillbicks commented 1 year ago

Yes, you are correct in your assumption. (should've mentioned that in the initial post.) extracted, made the changes and now trying to repack. I'll try your suggestion and report back.

I have to say though, the way linux handles OOM is really not ideal; to put it mildly. I also tried to limit the CPU and memory usage by starting signalbackup via systemd, didn't work either.

Thanks for your quick reply, I'll report back shortly.

hillbicks commented 1 year ago

Alright, that worked. Thank you very much!

signalbackup-tools signal-2023-06-04-21-32-51.backup --runsqlquery "DELETE FROM reaction WHERE _id = 5325"  --runsqlquery "pragma foreign_key_check" -o signal_fixed.backup
signalbackup-tools (signalbackup-tools) source version 20230603.171137 (OpenSSL)
Please provide passphrase for input file 'signal-2023-06-04-21-32-51.backup': ***** ***** ***** ***** ***** *****
Please provide passphrase for output file 'signal_fixed.backup' (leave empty to use input passphrase):
IV: (hex:) 44 d0 8a 18 91 14 a2 5e 80 ab 8d 51 90 9d 87 b5 (size: 16)
SALT: (hex:) 97 e1 8b 08 cb 87 0e e9 7f 1a 3c 76 6c 7c 77 2f 08 a7 f1 6f f3 3f 92 ad cb 11 80 b6 9d 1b 6a 21 (size: 32)
BACKUPKEY: (hex:) a6 51 25 13 7d 76 56 12 bd fb 06 e8 05 b5 11 89 99 50 f8 70 99 0d 33 d7 5c 34 ca 0f e8 7c 24 38 (size: 32)
CIPHERKEY: (hex:) f6 30 3c 7e 92 0c 32 99 f7 64 32 58 b9 e8 b2 5e 36 35 45 6d 63 89 da 8a 5c 45 c7 5c 37 86 10 9d (size: 32)
MACKEY: (hex:) 88 b3 61 ee ed c0 61 22 e8 a0 67 5e f7 8d d4 fd 50 66 08 a5 bf bb 4a 8d 80 cc 00 e1 66 c7 42 82 (size: 32)
COUNTER: 1154517528
Reading backup file...
FRAME 311388 (100.0%)... Read entire backup file...

done!

WARNING Foreign key constraint violated.
-----------------------------
| table    | parent  | fkid |
-----------------------------
| reaction | message | 1    |
-----------------------------
* Executing query: DELETE FROM reaction WHERE _id = 5325
Modified 1 rows
* Executing query: pragma foreign_key_check
(no results)

Exporting backup to 'signal_fixed.backup'
Writing HeaderFrame...
Writing DatabaseVersionFrame...
Writing SqlStatementFrame(s)...
Dealing with table 'avatar_picker'... 0/0 entries...
Dealing with table 'call_link'... 0/0 entries...
Dealing with table 'recipient'... 586/586 entries...done
Dealing with table 'thread'... 285/285 entries...done
Dealing with table 'message'... 231633/231633 entries...done
Dealing with table 'call'... 20/20 entries...done
Dealing with table 'cds'... 459/459 entries...done
Dealing with table 'chat_colors'... 0/0 entries...
Dealing with table 'distribution_list'... 1/1 entries...done
Dealing with table 'distribution_list_member'... 1/1 entries...done
Dealing with table 'donation_receipt'... 11/11 entries...done
Dealing with table 'drafts'... 1/1 entries...done
Dealing with table 'emoji_search'... 0/0 entries...
Dealing with table 'group_membership'... 104/104 entries...done
Dealing with table 'group_receipts'... 27172/27172 entries...done
Dealing with table 'groups'... 19/19 entries...done
Dealing with table 'identities'... 64/64 entries...done
Dealing with table 'mention'... 21/21 entries...done
Dealing with table 'msl_payload'... 4023/4023 entries...done
Dealing with table 'msl_message'... 4223/4223 entries...done
Dealing with table 'msl_recipient'... 14696/14696 entries...done
Dealing with table 'notification_profile'... 1/1 entries...done
Dealing with table 'notification_profile_allowed_members'... 0/0 entries...
Dealing with table 'notification_profile_schedule'... 1/1 entries...done
Dealing with table 'part'... 24/11209 entries...Warning: attachment data not found (rowid: 24, uniqueid: 1512475723510)
Dealing with table 'part'... 11209/11209 entries...done
Dealing with table 'payments'... 0/0 entries...
Dealing with table 'pending_pni_signature_message'... 0/0 entries...
Dealing with table 'pending_retry_receipts'... 0/0 entries...
Dealing with table 'push'... 0/0 entries...
Dealing with table 'reaction'... 5246/5246 entries...done
Dealing with table 'remapped_recipients'... 1/1 entries...done
Dealing with table 'remapped_threads'... 0/0 entries...
Dealing with table 'remote_megaphone'... 5/5 entries...done
Dealing with table 'sender_key_shared'... 0/0 entries...
Dealing with table 'sender_keys'... 0/0 entries...
Dealing with table 'sticker'... 103/103 entries...done
Dealing with table 'storage_key'... 4/4 entries...done
Dealing with table 'story_sends'... 0/0 entries...
Writing SharedPrefFrame(s)...
Writing KeyValueFrame(s)...
Writing Avatars...
Writing EndFrame...
Done!

Let me know if you want me to test a fix. I'll leave the extracted directory up to test again with a new version until then.

Again, thanks for your work on this programm and your help with this issue!

bepaald commented 1 year ago

Alright, that worked. Thank you very much!

Good! I'm glad it worked.

Let me know if you want me to test a fix. I'll leave the extracted directory up to test again with a new version until then.

That is very much appreciated, I was actually going to ask you to. I have just pushed an update that should fix the problem, so I would indeed love to hear if it works for you.

Again, thanks for your work on this programm and your help with this issue!

No problem, happy to help!

hillbicks commented 1 year ago

That seems to work, although with a caveat. Before I could ommit the -p switch and I would be asked for the passphrase (if using the directory as input). Now the repack process won't finish.

signalbackup-tools export --output signal_fixed.backup
signalbackup-tools (signalbackup-tools) source version 20230606.124028 (OpenSSL)
Opening from dir!
Reading database...
Reading HeaderFrame
Reading DatabaseVersionFrame
Reading SharedPreferenceFrame(s)
Reading KeyValueFrame(s)
Reading EndFrame
Reading AvatarFrames: 38/38
Reading AttachmentFrames
Reading StickerFrames
Done!

Exporting backup to 'signal_fixed.backup'
Need password to create encrypted backup file.
Failed to export backup to 'signal_fixed.backup'

adding -p with the passphrase to the command works though. process finishes just fine. I haven't imported the fixed file, but I did run the pragma check against the file

signalbackup-tools signal_fixed.backup  --runsqlquery "pragma foreign_key_check"
signalbackup-tools (signalbackup-tools) source version 20230606.124028 (OpenSSL)
Please provide passphrase for input file 'signal_fixed.backup': ***** ***** ***** ***** ***** *****
IV: (hex:) 44 d0 8a 18 91 14 a2 5e 80 ab 8d 51 90 9d 87 b5 (size: 16)
SALT: (hex:) 97 e1 8b 08 cb 87 0e e9 7f 1a 3c 76 6c 7c 77 2f 08 a7 f1 6f f3 3f 92 ad cb 11 80 b6 9d 1b 6a 21 (size: 32)
BACKUPKEY: (hex:) a6 51 25 13 7d 76 56 12 bd fb 06 e8 05 b5 11 89 99 50 f8 70 99 0d 33 d7 5c 34 ca 0f e8 7c 24 38 (size: 32)
CIPHERKEY: (hex:) f6 30 3c 7e 92 0c 32 99 f7 64 32 58 b9 e8 b2 5e 36 35 45 6d 63 89 da 8a 5c 45 c7 5c 37 86 10 9d (size: 32)
MACKEY: (hex:) 88 b3 61 ee ed c0 61 22 e8 a0 67 5e f7 8d d4 fd 50 66 08 a5 bf bb 4a 8d 80 cc 00 e1 66 c7 42 82 (size: 32)
COUNTER: 1154517528
Reading backup file...
FRAME 311387 (100.0%)... Read entire backup file...

done!
* Executing query: pragma foreign_key_check
(no results)

So thank you very much for the quick fix.

bepaald commented 1 year ago

That seems to work, although with a caveat. Before I could ommit the -p switch and I would be asked for the passphrase (if using the directory as input). Now the repack process won't finish.

Yes, that is expected: a backup file needs a passphrase. When you omit it, it will try to use the input passphrase by default, but when opening from a directory there is none (because it's not encrypted, and it's not stored in the backup file).

adding -p with the passphrase to the command works though. process finishes just fine. I haven't imported the fixed file, but I did run the pragma check against the file

Excellent. I don't think restoring the backup in necessary. If you still had the previous 'signal-fixed.backup' (from the workaround run), you could compare the two: as long as the made edits, and the passphrases used are exactly the same, the output should probably be bit-identical (could be checked with cmp or a checksum like md5sum). But honestly, the changed should only have affected memory usage, not the content.

So thank you very much for the quick fix.

Thank you for testing the fix and reporting back!

By the way, you might want to consider filing a bug report about the original foreign key issue at Signal. I love helping people out of course, but I think in general it would be preferred if this program (or at least its fixing-options) were never needed.

hillbicks commented 1 year ago

Yeah, that makes sense....

You're right, this is definitely a signal problem (and it is not the first time I had to use your programm because the import failed). I'll see what I can write up.

Thanks again!